浏览代码

Switch from libtiff to libdng

Martijn Braam 8 月之前
父节点
当前提交
2e9a623976
共有 2 个文件被更改,包括 349 次插入439 次删除
  1. 7 7
      CMakeLists.txt
  2. 342 432
      postprocess.c

+ 7 - 7
CMakeLists.txt

@@ -7,7 +7,7 @@ include(FindPkgConfig)
 
 find_package(PkgConfig REQUIRED)
 pkg_check_modules(RAW REQUIRED libraw)
-pkg_check_modules(TIFF REQUIRED libtiff-4)
+pkg_check_modules(DNG REQUIRED libdng)
 pkg_check_modules(JPEG REQUIRED libjpeg)
 pkg_check_modules(EXIF REQUIRED libexif)
 pkg_check_modules(CV REQUIRED opencv4)
@@ -15,11 +15,11 @@ pkg_check_modules(CV REQUIRED opencv4)
 add_compile_options(-Wall -Wextra -pedantic)
 
 add_executable(postprocessd main.c postprocess.c postprocess.h util.c util.h stacker.cpp stacker.h stackercpp.cpp stackercpp.h)
-target_link_libraries(postprocessd ${RAW_LIBRARIES} ${TIFF_LIBRARIES} ${JPEG_LIBRARIES} ${EXIF_LIBRARIES} ${CV_LIBRARIES})
-target_include_directories(postprocessd PUBLIC ${RAW_INCLUDE_DIRS} ${TIFF_INCLUDE_DIRS} ${JPEG_INCUDE_DIRS} ${EXIF_INCUDE_DIRS} ${CV_INCLUDE_DIRS})
-target_compile_options(postprocessd PUBLIC ${RAW_CFLAGS_OTHER} ${TIFF_CFLAGS_OTHER} ${JPEG_CFLAGS_OTHER} ${EXIF_CFLAGS_OTHER} ${CV_CFLAGS_OTHER})
+target_link_libraries(postprocessd ${RAW_LIBRARIES} ${DNG_LIBRARIES} ${JPEG_LIBRARIES} ${EXIF_LIBRARIES} ${CV_LIBRARIES})
+target_include_directories(postprocessd PUBLIC ${RAW_INCLUDE_DIRS} ${DNG_INCLUDE_DIRS} ${JPEG_INCUDE_DIRS} ${EXIF_INCUDE_DIRS} ${CV_INCLUDE_DIRS})
+target_compile_options(postprocessd PUBLIC ${RAW_CFLAGS_OTHER} ${DNG_CFLAGS_OTHER} ${JPEG_CFLAGS_OTHER} ${EXIF_CFLAGS_OTHER} ${CV_CFLAGS_OTHER})
 
 add_executable(postprocess-single single.c postprocess.c postprocess.h util.c util.h stacker.cpp stacker.h stackercpp.cpp stackercpp.h)
-target_link_libraries(postprocess-single ${RAW_LIBRARIES} ${TIFF_LIBRARIES} ${JPEG_LIBRARIES} ${EXIF_LIBRARIES} ${CV_LIBRARIES})
-target_include_directories(postprocess-single PUBLIC ${RAW_INCLUDE_DIRS} ${TIFF_INCLUDE_DIRS} ${JPEG_INCUDE_DIRS} ${EXIF_INCUDE_DIRS} ${CV_INCLUDE_DIRS})
-target_compile_options(postprocess-single PUBLIC ${RAW_CFLAGS_OTHER} ${TIFF_CFLAGS_OTHER} ${JPEG_CFLAGS_OTHER} ${EXIF_CFLAGS_OTHER} ${CV_CFLAGS_OTHER})
+target_link_libraries(postprocess-single ${RAW_LIBRARIES} ${DNG_LIBRARIES} ${JPEG_LIBRARIES} ${EXIF_LIBRARIES} ${CV_LIBRARIES})
+target_include_directories(postprocess-single PUBLIC ${RAW_INCLUDE_DIRS} ${DNG_INCLUDE_DIRS} ${JPEG_INCUDE_DIRS} ${EXIF_INCUDE_DIRS} ${CV_INCLUDE_DIRS})
+target_compile_options(postprocess-single PUBLIC ${RAW_CFLAGS_OTHER} ${DNG_CFLAGS_OTHER} ${JPEG_CFLAGS_OTHER} ${EXIF_CFLAGS_OTHER} ${CV_CFLAGS_OTHER})

+ 342 - 432
postprocess.c

@@ -2,492 +2,402 @@
 #include <string.h>
 #include <dirent.h>
 #include <libraw/libraw.h>
-#include <tiffio.h>
 #include <jpeglib.h>
 #include <libexif/exif-data.h>
 #include <time.h>
 #include <unistd.h>
+#include <libdng.h>
 #include "postprocess.h"
 #include "stacker.h"
 
-static void
-register_custom_tiff_tags(TIFF *tif)
-{
-	static const TIFFFieldInfo custom_fields[] = {
-		{DCPTAG_FORWARD_MATRIX_1,           -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, 1, 1,
-			"ForwardMatrix1"},
-		{DCPTAG_FORWARD_MATRIX_2,           -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, 1, 1,
-			"ForwardMatrix2"},
-		{DCPTAG_PROFILE_TONE_CURVE,         -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, 1, 1,
-			"ProfileToneCurve"},
-		{DCPTAG_PROFILE_HUE_SAT_MAP_DIMS,   -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, 1, 1,
-			"ProfileHueSatMapDims"},
-		{DCPTAG_PROFILE_HUE_SAT_MAP_DATA_1, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, 1, 1,
-			"ProfileHueSatMapData1"},
-		{DCPTAG_PROFILE_HUE_SAT_MAP_DATA_2, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, 1, 1,
-			"ProfileHueSatMapData2"},
-	};
-
-    // Add missing dng fields
-    TIFFMergeFieldInfo(tif, custom_fields,
-        sizeof(custom_fields) / sizeof(custom_fields[0]));
-}
-
 libraw_processed_image_t *
 debayer_file(char *filename)
 {
-    libraw_data_t *raw;
-    int ret;
-
-    raw = libraw_init(0);
-    if (libraw_open_file(raw, filename) != LIBRAW_SUCCESS) {
-        err("could not open file");
-        libraw_close(raw);
-    }
-
-    if (libraw_unpack(raw) != LIBRAW_SUCCESS) {
-        err("could not unpack file");
-        libraw_close(raw);
-    }
-
-    raw->params.no_auto_bright = 1;
-
-    if (libraw_dcraw_process(raw) != LIBRAW_SUCCESS) {
-        err("could not process file");
-        libraw_free_image(raw);
-        libraw_close(raw);
-    }
-
-    libraw_processed_image_t *proc_img = libraw_dcraw_make_mem_image(raw, &ret);
-    libraw_free_image(raw);
-
-    if (!proc_img) {
-        err("could not export image");
-        libraw_close(raw);
-    }
-    libraw_recycle(raw);
-    libraw_close(raw);
-    return proc_img;
+	libraw_data_t *raw;
+	int ret;
+
+	raw = libraw_init(0);
+	if (libraw_open_file(raw, filename) != LIBRAW_SUCCESS) {
+		err("could not open file");
+		libraw_close(raw);
+	}
+
+	if (libraw_unpack(raw) != LIBRAW_SUCCESS) {
+		err("could not unpack file");
+		libraw_close(raw);
+	}
+
+	raw->params.no_auto_bright = 1;
+
+	if (libraw_dcraw_process(raw) != LIBRAW_SUCCESS) {
+		err("could not process file");
+		libraw_free_image(raw);
+		libraw_close(raw);
+	}
+
+	libraw_processed_image_t *proc_img = libraw_dcraw_make_mem_image(raw, &ret);
+	libraw_free_image(raw);
+
+	if (!proc_img) {
+		err("could not export image");
+		libraw_close(raw);
+	}
+	libraw_recycle(raw);
+	libraw_close(raw);
+	return proc_img;
 }
 
 void
 save_jpeg(char *path, libraw_processed_image_t *data, int quality, ExifData *exif)
 {
-    unsigned char *exif_data;
-    unsigned int exif_len;
-    FILE *out = fopen(path, "wb");
-    if (!out) {
-        err("could not open target file");
-        exit(1);
-    }
-
-    struct jpeg_compress_struct jpeg;
-    struct jpeg_error_mgr error_mgr;
-    jpeg.err = jpeg_std_error(&error_mgr);
-    jpeg_create_compress(&jpeg);
-    jpeg_stdio_dest(&jpeg, out);
-    jpeg.image_width = data->width;
-    jpeg.image_height = data->height;
-    jpeg.input_components = 3;
-    jpeg.in_color_space = JCS_RGB;
-    jpeg_set_defaults(&jpeg);
-    jpeg_set_quality(&jpeg, quality, 1);
-    jpeg_start_compress(&jpeg, 1);
-
-    // Write exif
-    exif_data_save_data(exif, &exif_data, &exif_len);
-    jpeg_write_marker(&jpeg, JPEG_APP1, exif_data, exif_len);
-
-    // Write image data
-    JSAMPROW row_pointer;
-    int row_stride = jpeg.image_width * jpeg.input_components;
-
-    while (jpeg.next_scanline < jpeg.image_height) {
-        row_pointer = (JSAMPROW) &data->data[jpeg.next_scanline * row_stride];
-        jpeg_write_scanlines(&jpeg, &row_pointer, 1);
-    }
-
-    jpeg_finish_compress(&jpeg);
-    jpeg_destroy_compress(&jpeg);
-    fclose(out);
+	unsigned char *exif_data;
+	unsigned int exif_len;
+	FILE *out = fopen(path, "wb");
+	if (!out) {
+		err("could not open target file");
+		exit(1);
+	}
+
+	struct jpeg_compress_struct jpeg;
+	struct jpeg_error_mgr error_mgr;
+	jpeg.err = jpeg_std_error(&error_mgr);
+	jpeg_create_compress(&jpeg);
+	jpeg_stdio_dest(&jpeg, out);
+	jpeg.image_width = data->width;
+	jpeg.image_height = data->height;
+	jpeg.input_components = 3;
+	jpeg.in_color_space = JCS_RGB;
+	jpeg_set_defaults(&jpeg);
+	jpeg_set_quality(&jpeg, quality, 1);
+	jpeg_start_compress(&jpeg, 1);
+
+	// Write exif
+	exif_data_save_data(exif, &exif_data, &exif_len);
+	jpeg_write_marker(&jpeg, JPEG_APP1, exif_data, exif_len);
+
+	// Write image data
+	JSAMPROW row_pointer;
+	int row_stride = jpeg.image_width * jpeg.input_components;
+
+	while (jpeg.next_scanline < jpeg.image_height) {
+		row_pointer = (JSAMPROW) &data->data[jpeg.next_scanline * row_stride];
+		jpeg_write_scanlines(&jpeg, &row_pointer, 1);
+	}
+
+	jpeg_finish_compress(&jpeg);
+	jpeg_destroy_compress(&jpeg);
+	fclose(out);
 }
 
 static ExifEntry *
 init_tag(ExifData *exif, ExifIfd ifd, ExifTag tag)
 {
-    ExifEntry *entry;
-    /* Return an existing tag if one exists */
-    if (!((entry = exif_content_get_entry(exif->ifd[ifd], tag)))) {
-        /* Allocate a new entry */
-        entry = exif_entry_new();
-        assert(entry != NULL); /* catch an out of memory condition */
-        entry->tag = tag; /* tag must be set before calling
+	ExifEntry *entry;
+	/* Return an existing tag if one exists */
+	if (!((entry = exif_content_get_entry(exif->ifd[ifd], tag)))) {
+		/* Allocate a new entry */
+		entry = exif_entry_new();
+		assert(entry != NULL); /* catch an out of memory condition */
+		entry->tag = tag; /* tag must be set before calling
 				 exif_content_add_entry */
 
-        /* Attach the ExifEntry to an IFD */
-        exif_content_add_entry(exif->ifd[ifd], entry);
-
-        /* Allocate memory for the entry and fill with default data */
-        exif_entry_initialize(entry, tag);
-
-        /* Ownership of the ExifEntry has now been passed to the IFD.
-         * One must be very careful in accessing a structure after
-         * unref'ing it; in this case, we know "entry" won't be freed
-         * because the reference count was bumped when it was added to
-         * the IFD.
-         */
-        exif_entry_unref(entry);
-    }
-    return entry;
+		/* Attach the ExifEntry to an IFD */
+		exif_content_add_entry(exif->ifd[ifd], entry);
+
+		/* Allocate memory for the entry and fill with default data */
+		exif_entry_initialize(entry, tag);
+
+		/* Ownership of the ExifEntry has now been passed to the IFD.
+		 * One must be very careful in accessing a structure after
+		 * unref'ing it; in this case, we know "entry" won't be freed
+		 * because the reference count was bumped when it was added to
+		 * the IFD.
+		 */
+		exif_entry_unref(entry);
+	}
+	return entry;
 }
 
 void
 exif_set_string(ExifEntry *ed, const char *s, size_t size)
 {
-    if (ed->data) {
-        free(ed->data);
-    }
-    ed->components = size + 1;
-    ed->size = sizeof(char) * ed->components;
-    ed->data = (unsigned char *) malloc(ed->size);
-    if (!ed->data) {
-        err("Could not allocate exif string");
-        exit(1);
-    }
-    strncpy((char *) ed->data, (char *) s, size);
-    exif_entry_fix(ed);
+	if (ed->data) {
+		free(ed->data);
+	}
+	ed->components = size + 1;
+	ed->size = sizeof(char) * ed->components;
+	ed->data = (unsigned char *) malloc(ed->size);
+	if (!ed->data) {
+		err("Could not allocate exif string");
+		exit(1);
+	}
+	strncpy((char *) ed->data, (char *) s, size);
+	exif_entry_fix(ed);
 }
 
 ExifData *
 create_exif(struct Imagedata data)
 {
-    ExifEntry *entry;
-    ExifRational rational;
-    long denominator = 100000;
-    ExifData *exif = exif_data_new();
-    if (!exif) {
-        err("Could not initialize libexif");
-    }
-    exif_data_set_option(exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
-    exif_data_set_data_type(exif, EXIF_DATA_TYPE_COMPRESSED);
-    exif_data_set_byte_order(exif, EXIF_BYTE_ORDER_INTEL);
-    exif_data_fix(exif);
-
-    // Width
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION);
-    exif_set_long(entry->data, EXIF_BYTE_ORDER_INTEL, data.width);
-
-    // Height
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION);
-    exif_set_long(entry->data, EXIF_BYTE_ORDER_INTEL, data.height);
-
-    // Colorspace, 1=sRGB
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_COLOR_SPACE);
-    exif_set_long(entry->data, EXIF_BYTE_ORDER_INTEL, 1);
-
-    // Exposure program, enum
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_PROGRAM);
-    exif_set_long(entry->data, EXIF_BYTE_ORDER_INTEL, data.exposure_program);
-
-    // Camera make
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_MAKE);
-    exif_set_string(entry, data.make, strlen(data.make));
-
-    // Camera model
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_MODEL);
-    exif_set_string(entry, data.model, strlen(data.model));
-
-    // Processing software
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_SOFTWARE);
-    exif_set_string(entry, data.software, strlen(data.software));
-
-    // Various datetime fields
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME);
-    exif_set_string(entry, data.datetime, strlen(data.datetime));
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_DIGITIZED);
-    exif_set_string(entry, data.datetime, strlen(data.datetime));
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL);
-    exif_set_string(entry, data.datetime, strlen(data.datetime));
-
-    // Exposure time
-    rational.numerator = (long) ((double) data.exposure_time * denominator);
-    rational.denominator = denominator;
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_TIME);
-    exif_set_rational(entry->data, EXIF_BYTE_ORDER_INTEL, rational);
-
-    // fnumber
-    rational.numerator = (long) ((double) data.fnumber * denominator);
-    rational.denominator = denominator;
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_FNUMBER);
-    exif_set_rational(entry->data, EXIF_BYTE_ORDER_INTEL, rational);
-
-    // focal length
-    rational.numerator = (long) ((double) data.focal_length * denominator);
-    rational.denominator = denominator;
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH);
-    exif_set_rational(entry->data, EXIF_BYTE_ORDER_INTEL, rational);
-
-    // focal length, 35mm equiv
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM);
-    exif_set_short(entry->data, EXIF_BYTE_ORDER_INTEL, data.focal_length_35mm);
-
-    // ISO
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS);
-    exif_set_long(entry->data, EXIF_BYTE_ORDER_INTEL, data.isospeed);
-
-    // Flash
-    entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_FLASH);
-    exif_set_short(entry->data, EXIF_BYTE_ORDER_INTEL, data.flash);
-    return exif;
+	ExifEntry *entry;
+	ExifRational rational;
+	long denominator = 100000;
+	ExifData *exif = exif_data_new();
+	if (!exif) {
+		err("Could not initialize libexif");
+	}
+	exif_data_set_option(exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
+	exif_data_set_data_type(exif, EXIF_DATA_TYPE_COMPRESSED);
+	exif_data_set_byte_order(exif, EXIF_BYTE_ORDER_INTEL);
+	exif_data_fix(exif);
+
+	// Width
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION);
+	exif_set_long(entry->data, EXIF_BYTE_ORDER_INTEL, data.width);
+
+	// Height
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION);
+	exif_set_long(entry->data, EXIF_BYTE_ORDER_INTEL, data.height);
+
+	// Colorspace, 1=sRGB
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_COLOR_SPACE);
+	exif_set_long(entry->data, EXIF_BYTE_ORDER_INTEL, 1);
+
+	// Exposure program, enum
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_PROGRAM);
+	exif_set_long(entry->data, EXIF_BYTE_ORDER_INTEL, data.exposure_program);
+
+	// Camera make
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_MAKE);
+	exif_set_string(entry, data.make, strlen(data.make));
+
+	// Camera model
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_MODEL);
+	exif_set_string(entry, data.model, strlen(data.model));
+
+	// Processing software
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_SOFTWARE);
+	exif_set_string(entry, data.software, strlen(data.software));
+
+	// Various datetime fields
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME);
+	exif_set_string(entry, data.datetime, strlen(data.datetime));
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_DIGITIZED);
+	exif_set_string(entry, data.datetime, strlen(data.datetime));
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL);
+	exif_set_string(entry, data.datetime, strlen(data.datetime));
+
+	// Exposure time
+	rational.numerator = (long) ((double) data.exposure_time * denominator);
+	rational.denominator = denominator;
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_TIME);
+	exif_set_rational(entry->data, EXIF_BYTE_ORDER_INTEL, rational);
+
+	// fnumber
+	rational.numerator = (long) ((double) data.fnumber * denominator);
+	rational.denominator = denominator;
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_FNUMBER);
+	exif_set_rational(entry->data, EXIF_BYTE_ORDER_INTEL, rational);
+
+	// focal length
+	rational.numerator = (long) ((double) data.focal_length * denominator);
+	rational.denominator = denominator;
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH);
+	exif_set_rational(entry->data, EXIF_BYTE_ORDER_INTEL, rational);
+
+	// focal length, 35mm equiv
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM);
+	exif_set_short(entry->data, EXIF_BYTE_ORDER_INTEL, data.focal_length_35mm);
+
+	// ISO
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS);
+	exif_set_long(entry->data, EXIF_BYTE_ORDER_INTEL, data.isospeed);
+
+	// Flash
+	entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_FLASH);
+	exif_set_short(entry->data, EXIF_BYTE_ORDER_INTEL, data.flash);
+	return exif;
 }
 
 struct Imagedata
 read_exif(char *filename)
 {
-    struct Imagedata imagedata;
-    uint16_t subifd_count;
-    uint32_t *subifd_offsets;
-    uint32_t exif_offset;
-    uint32_t value_count;
-    uint16_t *short_array;
-    char *temp;
-
-    TIFF *im = TIFFOpen(filename, "r");
-
-    if (im == NULL) {
-        fprintf(stderr, "Could not open tiff");
-        exit(1);
-    }
-
-    if (TIFFGetField(im, TIFFTAG_MAKE, &temp) != 1) {
-        err("failed to read TIFFTAG_MAKE");
-    }
-    imagedata.make = strdup(temp);
-
-    if (TIFFGetField(im, TIFFTAG_MODEL, &temp) != 1) {
-        err("failed to read TIFFTAG_MODEL");
-    }
-    imagedata.model = strdup(temp);
-
-    if (TIFFGetField(im, TIFFTAG_SOFTWARE, &temp) != 1) {
-        err("failed to read TIFFTAG_SOFTWARE");
-    }
-    imagedata.software = strdup(temp);
-
-    if (TIFFGetField(im, TIFFTAG_DATETIME, &temp) != 1) {
-        err("failed to read TIFFTAG_DATETIME");
-    }
-    imagedata.datetime = strdup(temp);
-
-    if (TIFFGetField(im, TIFFTAG_ORIENTATION, &imagedata.orientation) != 1) {
-        err("failed to read TIFFTAG_ORIENTATION");
-    }
-
-    // Get the EXIF directory for the rest of the metadata
-    if (TIFFGetField(im, TIFFTAG_EXIFIFD, &exif_offset) != 1) {
-        err("failed to read TIFFTAG_EXIFIFD");
-    }
-
-    // Read the actual picture instead of the embedded thumbnail
-    if (TIFFGetField(im, TIFFTAG_SUBIFD, &subifd_count, &subifd_offsets)) {
-        if (subifd_count > 0) {
-            TIFFSetSubDirectory(im, subifd_offsets[0]);
-        }
-    }
-
-    if (TIFFGetField(im, TIFFTAG_IMAGELENGTH, &imagedata.height) != 1) {
-        err("failed to read TIFFTAG_IMAGELENGTH");
-    }
-    if (TIFFGetField(im, TIFFTAG_IMAGEWIDTH, &imagedata.width) != 1) {
-        err("failed to read TIFFTAG_IMAGEWIDTH");
-    }
-    if (TIFFGetField(im, TIFFTAG_BITSPERSAMPLE, &imagedata.bitspersample) != 1) {
-        err("failed to read TIFFTAG_BITSPERSAMPLE");
-    }
-
-    // Read the exif directory
-    TIFFReadEXIFDirectory(im, exif_offset);
-
-    if (TIFFGetField(im, EXIFTAG_EXPOSUREPROGRAM, &imagedata.exposure_program) != 1) {
-        err("failed to read EXIFTAG_EXPOSUREPROGRAM");
-    }
-
-    if (TIFFGetField(im, EXIFTAG_EXPOSURETIME, &imagedata.exposure_time) != 1) {
-        err("failed to read EXIFTAG_EXPOSURETIME");
-    }
-
-    if (TIFFGetField(im, EXIFTAG_PHOTOGRAPHICSENSITIVITY, &value_count, &short_array) != 1) {
-        err("failed to read EXIFTAG_PHOTOGRAPHICSENSITIVITY");
-    }else {
-        imagedata.isospeed = short_array[0];
-    }
-
-    if (TIFFGetField(im, EXIFTAG_FNUMBER, &imagedata.fnumber) != 1) {
-        err("failed to read EXIFTAG_FNUMBER");
-    }
-
-    if (TIFFGetField(im, EXIFTAG_FOCALLENGTH, &imagedata.focal_length) != 1) {
-        err("failed to read EXIFTAG_FOCALLENGTH");
-    }
-
-    if (TIFFGetField(im, EXIFTAG_FOCALLENGTHIN35MMFILM, &imagedata.focal_length_35mm) != 1) {
-        err("failed to read EXIFTAG_FOCALLENGTHIN35MMFILM");
-    }
-
-    if (TIFFGetField(im, EXIFTAG_FLASH, &imagedata.flash) != 1) {
-        err("failed to read EXIFTAG_FLASH");
-    }
-    TIFFClose(im);
-    return imagedata;
+	struct Imagedata imagedata;
+	uint16_t subifd_count;
+	uint32_t *subifd_offsets;
+	uint32_t exif_offset;
+	uint32_t value_count;
+	uint16_t *short_array;
+	char *temp;
+
+	libdng_info dng = {0};
+	if (libdng_read(&dng, filename) != 1) {
+		err("Could not load DNG file");
+	}
+	imagedata.make = strdup(dng.camera_make);
+	imagedata.model = strdup(dng.camera_model);
+	imagedata.datetime = malloc(20);
+	imagedata.software = strdup(dng.software);
+	strftime(imagedata.datetime, 20, "%Y:%m:%d %H:%M:%S", &dng.datetime);
+	imagedata.orientation = dng.orientation;
+	imagedata.width = dng.width;
+	imagedata.height = dng.height;
+	imagedata.bitspersample = dng.bit_depth;
+	imagedata.exposure_time = dng.exposure_time;
+	imagedata.exposure_program = dng.exposure_program;
+	imagedata.fnumber = dng.fnumber;
+	imagedata.isospeed = (uint16_t) dng.iso;
+	imagedata.focal_length = dng.focal_length;
+	imagedata.focal_length_35mm = (uint16_t) (dng.focal_length * dng.crop_factor);
+	imagedata.flash = 0;
 }
 
 static int
 filter_dng(const struct dirent *dir)
 {
-    if (!dir)
-        return 0;
-
-    if (dir->d_type == DT_REG) {
-        const char *ext = strrchr(dir->d_name, '.');
-        if ((!ext) || (ext == dir->d_name))
-            return 0;
-        else {
-            if (strcmp(ext, ".dng") == 0)
-                return 1;
-        }
-    }
-
-    return 0;
+	if (!dir)
+		return 0;
+
+	if (dir->d_type == DT_REG) {
+		const char *ext = strrchr(dir->d_name, '.');
+		if ((!ext) || (ext == dir->d_name))
+			return 0;
+		else {
+			if (strcmp(ext, ".dng") == 0)
+				return 1;
+		}
+	}
+
+	return 0;
 }
 
 void
-postprocess_setup()
+postprocess_setup(void)
 {
-    TIFFSetTagExtender(register_custom_tiff_tags);
+	libdng_init();
 }
 
 void
 postprocess_internal(char *burst_dir, char *target_dir, int keep)
 {
-    struct dirent **namelist;
-    int burst_size;
-    int first = 1;
-    struct Imagedata imagedata;
-    libraw_processed_image_t *decoded;
-    ExifData *exif;
-    char path[512];
-    char outpath[512];
-    char stackpath[512];
-
-    nice(19);
-
-    burst_size = scandir(burst_dir, &namelist, filter_dng, alphasort);
-    if (burst_size < 0) {
-        printf("oop\n");
-        exit(1);
-    }
-    if (burst_size == 0) {
-        printf("No DNG files found\n");
-        exit(1);
-    }
-    stacker_t *stacker = stacker_create(1);
-    while (burst_size--) {
-        fprintf(stderr, "DEBAYER %s\n", namelist[burst_size]->d_name);
-        snprintf(path, sizeof(path), "%s/%s", burst_dir, namelist[burst_size]->d_name);
-        if(keep)
-            snprintf(outpath, sizeof(outpath), "%s.%d.jpg", target_dir, burst_size);
-        else
-            snprintf(outpath, sizeof(outpath), "%s.jpg", target_dir);
-
-        if (first) {
-            imagedata = read_exif(path);
-            exif = create_exif(imagedata);
-        }
-        decoded = debayer_file(path);
-        if(keep || first) {
-            fprintf(stderr, "JPEG    %s\n", namelist[burst_size]->d_name);
-            save_jpeg(outpath, decoded, 90, exif);
-        }
-        fprintf(stderr, "CONVERG %s\n", namelist[burst_size]->d_name);
-        stacker_add_image(stacker, decoded->data, decoded->width, decoded->height);
-        free(namelist[burst_size]);
-
-        if (first) {
-            first = 0;
-        }
-    }
-    free(namelist);
-
-    fprintf(stderr, "STACK   stacked.jpg\n");
-    // Convert opencv result to a libraw struct and feed it in the jpeg encoder with the original exif data
-    char *stacked = stacker_get_result(stacker);
-    decoded->width = stacker_get_width(stacker);
-    decoded->height = stacker_get_height(stacker);
-    int result_size = decoded->width * decoded->height * 3;
-    libraw_processed_image_t *stacked_data = (libraw_processed_image_t *) malloc(
-        sizeof(libraw_processed_image_t) + result_size);
-    memset(stacked_data, 0, sizeof(libraw_processed_image_t));
-    stacked_data->colors = 3;
-    stacked_data->width = decoded->width;
-    stacked_data->height = decoded->height;
-    memmove(stacked_data->data, stacked, result_size);
-
-    // Save the final file
-    fprintf(stderr, "JPEG    stacked.jpg\n");
-    if(keep)
-        snprintf(stackpath, sizeof(stackpath), "%s.stacked.jpg", target_dir);
-    else
-        snprintf(stackpath, sizeof(stackpath), "%s.jpg", target_dir);
-
-    save_jpeg(stackpath, stacked_data, 90, exif);
+	struct dirent **namelist;
+	int burst_size;
+	int first = 1;
+	struct Imagedata imagedata;
+	libraw_processed_image_t *decoded;
+	ExifData *exif;
+	char path[512];
+	char outpath[512];
+	char stackpath[512];
+
+	nice(19);
+
+	burst_size = scandir(burst_dir, &namelist, filter_dng, alphasort);
+	if (burst_size < 0) {
+		printf("oop\n");
+		exit(1);
+	}
+	if (burst_size == 0) {
+		printf("No DNG files found\n");
+		exit(1);
+	}
+	stacker_t *stacker = stacker_create(1);
+	while (burst_size--) {
+		fprintf(stderr, "DEBAYER %s\n", namelist[burst_size]->d_name);
+		snprintf(path, sizeof(path), "%s/%s", burst_dir, namelist[burst_size]->d_name);
+		if (keep)
+			snprintf(outpath, sizeof(outpath), "%s.%d.jpg", target_dir, burst_size);
+		else
+			snprintf(outpath, sizeof(outpath), "%s.jpg", target_dir);
+
+		if (first) {
+			imagedata = read_exif(path);
+			exif = create_exif(imagedata);
+		}
+		decoded = debayer_file(path);
+		if (keep || first) {
+			fprintf(stderr, "JPEG    %s\n", namelist[burst_size]->d_name);
+			save_jpeg(outpath, decoded, 90, exif);
+		}
+		fprintf(stderr, "CONVERG %s\n", namelist[burst_size]->d_name);
+		stacker_add_image(stacker, decoded->data, decoded->width, decoded->height);
+		free(namelist[burst_size]);
+
+		if (first) {
+			first = 0;
+		}
+	}
+	free(namelist);
+
+	fprintf(stderr, "STACK   stacked.jpg\n");
+	// Convert opencv result to a libraw struct and feed it in the jpeg encoder with the original exif data
+	char *stacked = stacker_get_result(stacker);
+	decoded->width = stacker_get_width(stacker);
+	decoded->height = stacker_get_height(stacker);
+	int result_size = decoded->width * decoded->height * 3;
+	libraw_processed_image_t *stacked_data = (libraw_processed_image_t *) malloc(
+		sizeof(libraw_processed_image_t) + result_size);
+	memset(stacked_data, 0, sizeof(libraw_processed_image_t));
+	stacked_data->colors = 3;
+	stacked_data->width = decoded->width;
+	stacked_data->height = decoded->height;
+	memmove(stacked_data->data, stacked, result_size);
+
+	// Save the final file
+	fprintf(stderr, "JPEG    stacked.jpg\n");
+	if (keep)
+		snprintf(stackpath, sizeof(stackpath), "%s.stacked.jpg", target_dir);
+	else
+		snprintf(stackpath, sizeof(stackpath), "%s.jpg", target_dir);
+
+	save_jpeg(stackpath, stacked_data, 90, exif);
 }
 
 void
 postprocess_single(char *in_path, char *out_path, int quality, int verbose)
 {
-    libraw_processed_image_t *decoded;
-    libraw_processed_image_t *processed_data;
-    struct Imagedata imagedata;
-    ExifData *exif;
-    int width, height, result_size;
-    char *result;
-    clock_t timer;
-    stacker_t *stacker = stacker_create(verbose);
-
-    // Give the operating system more cpu time
-    nice(19);
-
-    // Parse exif data from original file
-    timer = clock();
-    imagedata = read_exif(in_path);
-    exif = create_exif(imagedata);
-    if (verbose) {
-        printf("[%.1fms] %s\n", (float) (clock() - timer) / CLOCKS_PER_SEC * 1000, "exif read");
-    }
-
-    // Convert the sensor data to rgb
-    timer = clock();
-    decoded = debayer_file(in_path);
-    if (verbose) {
-        printf("[%.1fms] %s\n", (float) (clock() - timer) / CLOCKS_PER_SEC * 1000, "debayer");
-    }
-
-    // Run the opencv postprocessing on the single frame
-    result = stacker_postprocess(stacker, decoded->data, decoded->width, decoded->height);
-    width = stacker_get_width(stacker);
-    height = stacker_get_height(stacker);
-
-    // Export the final jpeg with the original exif data
-    timer = clock();
-    result_size = width * height * 3;
-    processed_data = (libraw_processed_image_t *) malloc(sizeof(libraw_processed_image_t) + result_size);
-    memset(processed_data, 0, sizeof(libraw_processed_image_t));
-    processed_data->colors = 3;
-    processed_data->width = decoded->width;
-    processed_data->height = decoded->height;
-    memmove(processed_data->data, result, result_size);
-    save_jpeg(out_path, processed_data, quality, exif);
-    if (verbose) {
-        printf("[%.1fms] %s\n", (float) (clock() - timer) / CLOCKS_PER_SEC * 1000, "export");
-    }
+	libraw_processed_image_t *decoded;
+	libraw_processed_image_t *processed_data;
+	struct Imagedata imagedata;
+	ExifData *exif;
+	int width, height, result_size;
+	char *result;
+	clock_t timer;
+	stacker_t *stacker = stacker_create(verbose);
+
+	// Give the operating system more cpu time
+	nice(19);
+
+	// Parse exif data from original file
+	timer = clock();
+	imagedata = read_exif(in_path);
+	exif = create_exif(imagedata);
+	if (verbose) {
+		printf("[%.1fms] %s\n", (float) (clock() - timer) / CLOCKS_PER_SEC * 1000, "exif read");
+	}
+
+	// Convert the sensor data to rgb
+	timer = clock();
+	decoded = debayer_file(in_path);
+	if (verbose) {
+		printf("[%.1fms] %s\n", (float) (clock() - timer) / CLOCKS_PER_SEC * 1000, "debayer");
+	}
+
+	// Run the opencv postprocessing on the single frame
+	result = stacker_postprocess(stacker, decoded->data, decoded->width, decoded->height);
+	width = stacker_get_width(stacker);
+	height = stacker_get_height(stacker);
+
+	// Export the final jpeg with the original exif data
+	timer = clock();
+	result_size = width * height * 3;
+	processed_data = (libraw_processed_image_t *) malloc(sizeof(libraw_processed_image_t) + result_size);
+	memset(processed_data, 0, sizeof(libraw_processed_image_t));
+	processed_data->colors = 3;
+	processed_data->width = decoded->width;
+	processed_data->height = decoded->height;
+	memmove(processed_data->data, result, result_size);
+	save_jpeg(out_path, processed_data, quality, exif);
+	if (verbose) {
+		printf("[%.1fms] %s\n", (float) (clock() - timer) / CLOCKS_PER_SEC * 1000, "export");
+	}
 }