Ver código fonte

Add the focal length metadata

Martijn Braam 1 ano atrás
pai
commit
4a6d091ce6
6 arquivos alterados com 51 adições e 4 exclusões
  1. 5 0
      include/libdng.h
  2. 3 0
      man/makedng.1.scd
  3. 25 1
      src/libdng.c
  4. 4 2
      tests/check_dng.c
  5. 1 0
      tests/test_dng_validate.sh
  6. 13 1
      util/makedng.c

+ 5 - 0
include/libdng.h

@@ -19,6 +19,8 @@ typedef struct {
 		float exposure_time;
 		uint32_t iso;
 		float fnumber;
+		float focal_length;
+		float crop_factor;
 
 		// Raw image data
 		uint16_t bayer_pattern_dimensions[2];
@@ -136,6 +138,9 @@ libdng_set_iso(libdng_info *dng, uint32_t isospeed);
 EXPORT int
 libdng_set_fnumber(libdng_info *dng, float fnumber);
 
+EXPORT int
+libdng_set_focal_length(libdng_info *dng, float focal_length, float crop_factor);
+
 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

@@ -55,6 +55,9 @@ metadata to correctly render the file.
 *-f fnumber*
 	Set the aperture size, or f-number of the picture (2.2 for f/2.2)
 
+*-l focal-length,crop-factor* | *-l focal-length*
+	Set the focal length for the lens. If no crop factor for the system is supplied a 35mm full-frame sensor is assumed.
+
 # PIXEL FORMATS
 
 The pixel format argument accepts the following values:

+ 25 - 1
src/libdng.c

@@ -61,6 +61,8 @@ libdng_new(libdng_info *dng)
 	dng->exposure_time = 0.0f;
 	dng->iso = 0;
 	dng->fnumber = 0.0f;
+	dng->crop_factor = 1.0f;
+	dng->focal_length = 0.0f;
 }
 
 int
@@ -237,6 +239,23 @@ libdng_set_fnumber(libdng_info *dng, float fnumber)
 	return 1;
 }
 
+int
+libdng_set_focal_length(libdng_info *dng, float focal_length, float crop_factor)
+{
+	if (dng == NULL)
+		return 0;
+
+	if (focal_length < 0.0f)
+		return 0;
+
+	if (crop_factor < 0.0f)
+		return 0;
+
+	dng->focal_length = focal_length;
+	dng->crop_factor = crop_factor;
+	return 1;
+}
+
 int
 libdng_write(libdng_info *dng, const char *path, unsigned int width, unsigned int height, const uint8_t *data,
 	size_t length)
@@ -382,7 +401,12 @@ libdng_write_with_thumbnail(libdng_info *dng, const char *path, unsigned int wid
 	if (dng->fnumber > 0) {
 		TIFFSetField(tif, EXIFTAG_FNUMBER, dng->fnumber);
 	}
-
+	if (dng->focal_length > 0) {
+		TIFFSetField(tif, EXIFTAG_FOCALLENGTH, dng->focal_length);
+		if (dng->crop_factor != 1.0f) {
+			TIFFSetField(tif, EXIFTAG_FOCALLENGTHIN35MMFILM, (uint16_t) (dng->focal_length * dng->crop_factor));
+		}
+	}
 
 	uint64_t exif_offset = 0;
 	if (!TIFFWriteCustomDirectory(tif, &exif_offset)) {

+ 4 - 2
tests/check_dng.c

@@ -17,7 +17,7 @@ check_str_tag(TIFF *im, uint32_t tag, const char *name, const char *expected)
 static enum greatest_test_res
 check_int_tag(TIFF *im, uint32_t tag, const char *name, int expected)
 {
-	uint32_t temp;
+	uint32_t temp = 0;
 	if (TIFFGetField(im, tag, &temp) != 1) {
 			FAILm(name);
 	}
@@ -47,6 +47,7 @@ TEST generate_simple_dng(void)
 		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));
+		ASSERT_EQm("Set fnumber", 1, libdng_set_focal_length(&info, 50.0f, 1.5f));
 	uint8_t *data = malloc(1280 * 720);
 		ASSERT_EQm("Write DNG", 1, libdng_write(&info, "test.dng", 1280, 720, data, 1280 * 720));
 	free(data);
@@ -94,7 +95,8 @@ TEST generate_simple_dng(void)
 	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));
-
+		CHECK_CALL(check_float_tag(im, EXIFTAG_FOCALLENGTH, "FOCALLENGTH", 50.0f));
+		CHECK_CALL(check_int_tag(im, EXIFTAG_FOCALLENGTHIN35MMFILM, "FOCALLENGTHIN35MMFILM", 75));
 		PASS();
 }
 

+ 1 - 0
tests/test_dng_validate.sh

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

+ 13 - 1
util/makedng.c

@@ -51,8 +51,10 @@ main(int argc, char *argv[])
 	float exposure_time = 0;
 	uint32_t iso = 0;
 	float fnumber = 0.0f;
+	float focal_length = 0.0f;
+	float crop_factor = 1.0f;
 
-	while ((c = getopt(argc, argv, "w:h:p:o:m:s:c:n:b:e:t:i:f:")) != -1) {
+	while ((c = getopt(argc, argv, "w:h:p:o:m:s:c:n:b:e:t:i:f:l:")) != -1) {
 		switch (c) {
 			case 'w':
 				val = strtol(optarg, &end, 10);
@@ -110,6 +112,13 @@ main(int argc, char *argv[])
 			case 'f':
 				fnumber = strtof(optarg, &end);
 				break;
+			case 'l':
+				val = sscanf(optarg, "%f,%f", &focal_length, &crop_factor);
+				if (val != 2 && val != 1) {
+					fprintf(stderr, "Invalid format for -l. Specify -l $length,$cropfactor or -l $length\n");
+					return 1;
+				}
+				break;
 			case '?':
 				if (optopt == 'd' || optopt == 'l') {
 					fprintf(stderr, "Option -%c requires an argument.\n", optopt);
@@ -184,6 +193,9 @@ main(int argc, char *argv[])
 	if (fnumber > 0) {
 		libdng_set_fnumber(&info, fnumber);
 	}
+	if (focal_length > 0) {
+		libdng_set_focal_length(&info, focal_length, crop_factor);
+	}
 
 	printf("Reading %s...\n", argv[optind]);
 	FILE *src = fopen(argv[optind], "r");