Browse Source

Add the f-number metadata

Martijn Braam 1 year ago
parent
commit
388d5e9104
6 changed files with 38 additions and 2 deletions
  1. 4 0
      include/libdng.h
  2. 3 0
      man/makedng.1.scd
  3. 19 1
      src/libdng.c
  4. 2 0
      tests/check_dng.c
  5. 1 0
      tests/test_dng_validate.sh
  6. 9 1
      util/makedng.c

+ 4 - 0
include/libdng.h

@@ -18,6 +18,7 @@ typedef struct {
 		uint16_t exposure_program;
 		float exposure_time;
 		uint32_t iso;
+		float fnumber;
 
 		// Raw image data
 		uint16_t bayer_pattern_dimensions[2];
@@ -132,6 +133,9 @@ libdng_set_exposure_time(libdng_info *dng, float seconds);
 EXPORT int
 libdng_set_iso(libdng_info *dng, uint32_t isospeed);
 
+EXPORT int
+libdng_set_fnumber(libdng_info *dng, float fnumber);
+
 EXPORT int
 libdng_write(libdng_info *dng, const char *path, unsigned int width, unsigned int height, const uint8_t *data,
 	size_t length);

+ 3 - 0
man/makedng.1.scd

@@ -52,6 +52,9 @@ metadata to correctly render the file.
 *-i iso-speed*
 	Set the ISO speed rating for the picture
 
+*-f fnumber*
+	Set the aperture size, or f-number of the picture (2.2 for f/2.2)
+
 # PIXEL FORMATS
 
 The pixel format argument accepts the following values:

+ 19 - 1
src/libdng.c

@@ -60,6 +60,7 @@ libdng_new(libdng_info *dng)
 
 	dng->exposure_time = 0.0f;
 	dng->iso = 0;
+	dng->fnumber = 0.0f;
 }
 
 int
@@ -223,6 +224,19 @@ libdng_set_iso(libdng_info *dng, uint32_t isospeed)
 	return 1;
 }
 
+int
+libdng_set_fnumber(libdng_info *dng, float fnumber)
+{
+	if (dng == NULL)
+		return 0;
+
+	if (fnumber < 0.0f)
+		return 0;
+
+	dng->fnumber = fnumber;
+	return 1;
+}
+
 int
 libdng_write(libdng_info *dng, const char *path, unsigned int width, unsigned int height, const uint8_t *data,
 	size_t length)
@@ -362,9 +376,13 @@ libdng_write_with_thumbnail(libdng_info *dng, const char *path, unsigned int wid
 	if (dng->exposure_time > 0) {
 		TIFFSetField(tif, EXIFTAG_EXPOSURETIME, dng->exposure_time);
 	}
-	if(dng->iso > 0) {
+	if (dng->iso > 0) {
 		TIFFSetField(tif, EXIFTAG_ISOSPEEDRATINGS, 1, &dng->iso);
 	}
+	if (dng->fnumber > 0) {
+		TIFFSetField(tif, EXIFTAG_FNUMBER, dng->fnumber);
+	}
+
 
 	uint64_t exif_offset = 0;
 	if (!TIFFWriteCustomDirectory(tif, &exif_offset)) {

+ 2 - 0
tests/check_dng.c

@@ -46,6 +46,7 @@ TEST generate_simple_dng(void)
 		ASSERT_EQm("Set software", 1, libdng_set_software(&info, "Software"));
 		ASSERT_EQm("Set orientation", 1, libdng_set_orientation(&info, 4));
 		ASSERT_EQm("Set exposuretime", 1, libdng_set_exposure_time(&info, 0.04f));
+		ASSERT_EQm("Set fnumber", 1, libdng_set_fnumber(&info, 2.8f));
 	uint8_t *data = malloc(1280 * 720);
 		ASSERT_EQm("Write DNG", 1, libdng_write(&info, "test.dng", 1280, 720, data, 1280 * 720));
 	free(data);
@@ -92,6 +93,7 @@ TEST generate_simple_dng(void)
 	// Switch to the EXIF block with the generic picture metadata
 	TIFFReadEXIFDirectory(im, exif_offset);
 		CHECK_CALL(check_float_tag(im, EXIFTAG_EXPOSURETIME, "EXPOSURETIME", 0.04f));
+		CHECK_CALL(check_float_tag(im, EXIFTAG_FNUMBER, "FNUMBER", 2.8f));
 
 		PASS();
 }

+ 1 - 0
tests/test_dng_validate.sh

@@ -34,6 +34,7 @@ $makedng -w 1280 -h 720 -p RGGB \
   -e 2 \
   -t 0.01 \
   -i 1600 \
+  -f 2.8 \
   scratch/data.rgb scratch/fields.dng
 
 # Validate DNG

+ 9 - 1
util/makedng.c

@@ -24,6 +24,7 @@ usage(char *name)
 	fprintf(stderr, "  -e program     Set the exposure program in EXIF, 0-8\n");
 	fprintf(stderr, "  -t seconds     Set the exposure time in seconds\n");
 	fprintf(stderr, "  -i speed       Set the ISO speed rating\n");
+	fprintf(stderr, "  -f fnumber     Set the aperture as f/value\n");
 }
 
 int
@@ -49,8 +50,9 @@ main(int argc, char *argv[])
 	uint16_t exposure_program = 0;
 	float exposure_time = 0;
 	uint32_t iso = 0;
+	float fnumber = 0.0f;
 
-	while ((c = getopt(argc, argv, "w:h:p:o:m:s:c:n:b:e:t:i:")) != -1) {
+	while ((c = getopt(argc, argv, "w:h:p:o:m:s:c:n:b:e:t:i:f:")) != -1) {
 		switch (c) {
 			case 'w':
 				val = strtol(optarg, &end, 10);
@@ -105,6 +107,9 @@ main(int argc, char *argv[])
 				val = strtol(optarg, &end, 10);
 				iso = (uint32_t) val;
 				break;
+			case 'f':
+				fnumber = strtof(optarg, &end);
+				break;
 			case '?':
 				if (optopt == 'd' || optopt == 'l') {
 					fprintf(stderr, "Option -%c requires an argument.\n", optopt);
@@ -176,6 +181,9 @@ main(int argc, char *argv[])
 	if (iso > 0) {
 		libdng_set_iso(&info, iso);
 	}
+	if (fnumber > 0) {
+		libdng_set_fnumber(&info, fnumber);
+	}
 
 	printf("Reading %s...\n", argv[optind]);
 	FILE *src = fopen(argv[optind], "r");