Browse Source

Write more metadata using libdng

Martijn Braam 1 year ago
parent
commit
da68a1c96a
3 changed files with 34 additions and 254 deletions
  1. 0 146
      src/dcp.c
  2. 0 11
      src/dcp.h
  3. 34 97
      src/process_pipeline.c

+ 0 - 146
src/dcp.c

@@ -2,154 +2,8 @@
 
 #include <stdbool.h>
 #include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 #include <unistd.h>
 
-unsigned int
-get_int32(const unsigned char *buffer, size_t offset)
-{
-        return (buffer[offset + 3] << 24) | (buffer[offset + 2] << 16) |
-               (buffer[offset + 1] << 8) | (buffer[offset]);
-}
-
-unsigned int
-get_int16(const unsigned char *buffer, size_t offset)
-{
-        return (buffer[offset + 1] << 8) | (buffer[offset]);
-}
-
-float
-get_float(unsigned char *buffer, size_t offset)
-{
-        float f;
-        unsigned char b[] = { buffer[offset + 0],
-                              buffer[offset + 1],
-                              buffer[offset + 2],
-                              buffer[offset + 3] };
-        memcpy(&f, &b, sizeof(f));
-        return f;
-}
-
-float
-get_srational(unsigned char *buffer, size_t offset)
-{
-        int a = (int)get_int32(buffer, offset);
-        int b = (int)get_int32(buffer, offset + 4);
-        return (float)a / (float)b;
-}
-
-struct MPCameraCalibration
-parse_calibration_file(const char *path)
-{
-        FILE *fp;
-        size_t size;
-        unsigned char *buffer;
-
-        struct MPCameraCalibration result = { 0 };
-
-        fp = fopen(path, "rb");
-        if (fp == NULL) {
-                return result;
-        }
-
-        fseek(fp, 0, SEEK_END);
-        size = ftell(fp);
-        fseek(fp, 0, SEEK_SET);
-        buffer = malloc(sizeof(char) * size);
-        size_t ret = fread(buffer, 1, size, fp);
-        if (ret != size) {
-                return result;
-        }
-        fclose(fp);
-
-        if (buffer[0] != 'I' || buffer[1] != 'I') {
-                fprintf(stderr, "Magic for DCP file incorrect\n");
-                return result;
-        }
-        if (buffer[2] != 0x52 || buffer[3] != 0x43) {
-                fprintf(stderr, "Invalid DCP version\n");
-                return result;
-        }
-
-        unsigned int ifd0 = get_int32(buffer, 4);
-        unsigned int tag_count = get_int16(buffer, ifd0);
-
-        for (int i = 0; i < tag_count; i++) {
-                int tag_offset = ifd0 + 2 + (i * 12);
-                unsigned int tag = get_int16(buffer, tag_offset + 0);
-                unsigned int type = get_int16(buffer, tag_offset + 2);
-                unsigned int count = get_int32(buffer, tag_offset + 4);
-                unsigned int offset = get_int32(buffer, tag_offset + 8);
-
-                switch (tag) {
-                case DCPTAG_COLOR_MATRIX_1:
-                        for (int j = 0; j < 9; j++) {
-                                float point =
-                                        get_srational(buffer, offset + (j * 8));
-                                result.color_matrix_1[j] = point;
-                        }
-                        break;
-                case DCPTAG_COLOR_MATRIX_2:
-                        for (int j = 0; j < 9; j++) {
-                                float point =
-                                        get_srational(buffer, offset + (j * 8));
-                                result.color_matrix_2[j] = point;
-                        }
-                        break;
-                case DCPTAG_FORWARD_MATRIX_1:
-                        for (int j = 0; j < 9; j++) {
-                                float point =
-                                        get_srational(buffer, offset + (j * 8));
-                                result.forward_matrix_1[j] = point;
-                        }
-                        break;
-                case DCPTAG_FORWARD_MATRIX_2:
-                        for (int j = 0; j < 9; j++) {
-                                float point =
-                                        get_srational(buffer, offset + (j * 8));
-                                result.forward_matrix_2[j] = point;
-                        }
-                        break;
-                case DCPTAG_CALIBRATION_ILLUMINANT_1:
-                        result.illuminant_1 = offset;
-                        break;
-                case DCPTAG_CALIBRATION_ILLUMINANT_2:
-                        result.illuminant_2 = offset;
-                        break;
-                case DCPTAG_PROFILE_TONE_CURVE:
-                        result.tone_curve = malloc(count * sizeof(float));
-                        result.tone_curve_length = count;
-                        for (int j = 0; j < count; j++) {
-                                result.tone_curve[j] =
-                                        get_float(buffer, offset + (j * 4));
-                        }
-                        break;
-                case DCPTAG_PROFILE_HUE_SAT_MAP_DIMS:
-                        result.hue_sat_map_dims[0] = get_int32(buffer, offset);
-                        result.hue_sat_map_dims[1] = get_int32(buffer, offset + 4);
-                        result.hue_sat_map_dims[2] = get_int32(buffer, offset + 8);
-                        break;
-                case DCPTAG_PROFILE_HUE_SAT_MAP_DATA_1:
-                        result.hue_sat_map_data_1 = malloc(count * sizeof(float));
-                        for (int j = 0; j < count; j++) {
-                                result.hue_sat_map_data_1[j] =
-                                        get_float(buffer, offset + (j * 4));
-                        }
-                        break;
-                case DCPTAG_PROFILE_HUE_SAT_MAP_DATA_2:
-                        result.hue_sat_map_data_2 = malloc(count * sizeof(float));
-                        for (int j = 0; j < count; j++) {
-                                result.hue_sat_map_data_2[j] =
-                                        get_float(buffer, offset + (j * 4));
-                        }
-                        break;
-                }
-        }
-
-        return result;
-}
-
 bool
 find_calibration_by_model(char *conffile, char *model, const char *sensor)
 {

+ 0 - 11
src/dcp.h

@@ -17,17 +17,6 @@ struct MPCameraCalibration {
         float *hue_sat_map_data_2;
 };
 
-#define DCPTAG_COLOR_MATRIX_1 50721
-#define DCPTAG_COLOR_MATRIX_2 50722
-#define DCPTAG_PROFILE_HUE_SAT_MAP_DIMS 50937
-#define DCPTAG_PROFILE_HUE_SAT_MAP_DATA_1 50938
-#define DCPTAG_PROFILE_HUE_SAT_MAP_DATA_2 50939
-#define DCPTAG_PROFILE_TONE_CURVE 50940
-#define DCPTAG_CALIBRATION_ILLUMINANT_1 50778
-#define DCPTAG_CALIBRATION_ILLUMINANT_2 50779
-#define DCPTAG_FORWARD_MATRIX_1 50964
-#define DCPTAG_FORWARD_MATRIX_2 50965
-
 struct MPCameraCalibration parse_calibration_file(const char *path);
 
 bool find_calibration(char *conffile, const char *sensor);

+ 34 - 97
src/process_pipeline.c

@@ -481,24 +481,51 @@ process_image_for_preview(const uint8_t *image)
 static void
 process_image_for_capture(const uint8_t *image, int count)
 {
-        time_t rawtime;
-        time(&rawtime);
-        struct tm tim = *(localtime(&rawtime));
-
-        char datetime[20] = { 0 };
-        strftime(datetime, 20, "%Y:%m:%d %H:%M:%S", &tim);
-
         char fname[255];
         sprintf(fname, "%s/%d.dng", burst_dir, count);
 
+        uint16_t orientation;
+        if (state_proc.device_rotation == 0) {
+                orientation = state_proc.mode->mirrored ?
+                                      LIBDNG_ORIENTATION_TOPRIGHT :
+                                      LIBDNG_ORIENTATION_TOPLEFT;
+        } else if (state_proc.device_rotation == 90) {
+                orientation = state_proc.mode->mirrored ?
+                                      LIBDNG_ORIENTATION_RIGHTBOT :
+                                      LIBDNG_ORIENTATION_LEFTBOT;
+        } else if (state_proc.device_rotation == 180) {
+                orientation = state_proc.mode->mirrored ?
+                                      LIBDNG_ORIENTATION_BOTLEFT :
+                                      LIBDNG_ORIENTATION_BOTRIGHT;
+        } else {
+                orientation = state_proc.mode->mirrored ?
+                                      LIBDNG_ORIENTATION_LEFTTOP :
+                                      LIBDNG_ORIENTATION_RIGHTTOP;
+        }
+
         libdng_info dng = { 0 };
         libdng_new(&dng);
 
+        libdng_set_datetime_now(&dng);
         libdng_set_mode_from_pixfmt(&dng, state_proc.mode->v4l_pixfmt);
         libdng_set_make_model(&dng,
                               state_proc.configuration->make,
                               state_proc.configuration->model);
+        libdng_set_orientation(&dng, orientation);
+        libdng_set_software(&dng, "Megapixels");
+        libdng_set_neutral(&dng, state_proc.red, 1.0f, state_proc.blue);
+        libdng_set_analog_balance(&dng,
+                                  state_proc.balance[0],
+                                  state_proc.balance[1],
+                                  state_proc.balance[2]);
+
+        if (!state_proc.exposure.manual) {
+                libdng_set_exposure_program(&dng, LIBDNG_EXPOSUREPROGRAM_NORMAL);
+        } else {
+                libdng_set_exposure_program(&dng, LIBDNG_EXPOSUREPROGRAM_MANUAL);
+        }
 
+        printf("Writing frame to %s\n", fname);
         libdng_write(&dng,
                      fname,
                      state_proc.mode->width,
@@ -507,84 +534,6 @@ process_image_for_capture(const uint8_t *image, int count)
                      count);
         libdng_free(&dng);
 
-        uint16_t orientation;
-        if (state_proc.device_rotation == 0) {
-                orientation = state_proc.mode->mirrored ? ORIENTATION_TOPRIGHT :
-                                                          ORIENTATION_TOPLEFT;
-        } else if (state_proc.device_rotation == 90) {
-                orientation = state_proc.mode->mirrored ? ORIENTATION_RIGHTBOT :
-                                                          ORIENTATION_LEFTBOT;
-        } else if (state_proc.device_rotation == 180) {
-                orientation = state_proc.mode->mirrored ? ORIENTATION_BOTLEFT :
-                                                          ORIENTATION_BOTRIGHT;
-        } else {
-                orientation = state_proc.mode->mirrored ? ORIENTATION_LEFTTOP :
-                                                          ORIENTATION_RIGHTTOP;
-        }
-        TIFFSetField(tif, TIFFTAG_ORIENTATION, orientation);
-        TIFFSetField(tif, TIFFTAG_DATETIME, datetime);
-        TIFFSetField(tif, TIFFTAG_SOFTWARE, "Megapixels");
-
-        static float neutral[] = { 1.0f, 1.0f, 1.0f };
-        neutral[0] = state_proc.red;
-        neutral[2] = state_proc.blue;
-        TIFFSetField(tif, TIFFTAG_ASSHOTNEUTRAL, 3, neutral);
-        TIFFSetField(tif, TIFFTAG_ANALOGBALANCE, 3, state_proc.balance);
-
-        // Write black thumbnail, only windows uses this
-        {
-                unsigned char *buf = (unsigned char *)calloc(
-                        1, (state_proc.mode->width >> 4) * 3);
-                for (int row = 0; row < (state_proc.mode->height >> 4); row++) {
-                        TIFFWriteScanline(tif, buf, row, 0);
-                }
-                free(buf);
-        }
-        TIFFWriteDirectory(tif);
-
-        printf("TIFF version %d\n", TIFFLIB_VERSION);
-        int whitelevel =
-                (1 << libmegapixels_format_bits_per_pixel(state_proc.mode->format)) -
-                1;
-        TIFFSetField(tif, TIFFTAG_WHITELEVEL, 1, &whitelevel);
-        TIFFCheckpointDirectory(tif);
-        printf("Writing frame to %s\n", fname);
-
-        uint8_t *output_image = (uint8_t *)image;
-
-        // Repack 10-bit image from sensor format into a sequencial format
-        if (libmegapixels_format_bits_per_pixel(state_proc.mode->format) == 10) {
-                output_image = malloc(
-                        libmegapixels_mode_width_to_bytes(state_proc.mode->format,
-                                                          state_proc.mode->width) *
-                        state_proc.mode->height);
-
-                repack_image_sequencial(image, output_image, state_proc.mode);
-        }
-
-        for (int row = 0; row < state_proc.mode->height; row++) {
-                TIFFWriteScanline(tif,
-                                  (void *)output_image +
-                                          (row * libmegapixels_mode_width_to_bytes(
-                                                         state_proc.mode->format,
-                                                         state_proc.mode->width)),
-                                  row,
-                                  0);
-        }
-        TIFFWriteDirectory(tif);
-
-        if (output_image != image)
-                free(output_image);
-
-        // Add an EXIF block to the tiff
-        TIFFCreateEXIFDirectory(tif);
-        // 1 = manual, 2 = full auto, 3 = aperture priority, 4 = shutter priority
-        if (!state_proc.exposure.manual) {
-                TIFFSetField(tif, EXIFTAG_EXPOSUREPROGRAM, 2);
-        } else {
-                TIFFSetField(tif, EXIFTAG_EXPOSUREPROGRAM, 1);
-        }
-
         /*
         TIFFSetField(tif,
                      EXIFTAG_EXPOSURETIME,
@@ -610,8 +559,6 @@ process_image_for_capture(const uint8_t *image, int count)
         }
          */
 
-        TIFFSetField(tif, EXIFTAG_DATETIMEORIGINAL, datetime);
-        TIFFSetField(tif, EXIFTAG_DATETIMEDIGITIZED, datetime);
         /*
         if (pr_camera->fnumber) {
                 TIFFSetField(tif, EXIFTAG_FNUMBER, pr_camera->fnumber);
@@ -626,16 +573,6 @@ process_image_for_capture(const uint8_t *image, int count)
         pr_camera->cropfactor));
         }
          */
-        uint64_t exif_offset = 0;
-        TIFFWriteCustomDirectory(tif, &exif_offset);
-        TIFFFreeDirectory(tif);
-
-        // Update exif pointer
-        TIFFSetDirectory(tif, 0);
-        TIFFSetField(tif, TIFFTAG_EXIFIFD, exif_offset);
-        TIFFRewriteDirectory(tif);
-
-        TIFFClose(tif);
 }
 
 static void