Skip to content

compensate exposure based on "dynamic range" #7705

Description

@dtorop

Is your feature request related to a problem? Please describe.
Some cameras allow for "dynamic range" modes which effectively reduce the ISO so as not to clip highlights in images requiring a great deal of exposure latitude. This pushes information into the shadows. Such a raw image, when opened in darkroom view, appears underexposed compared to its embedded JPEG. It is possible to increase the exposure appropriately by hand, but this often exceeds the "soft limit" of the exposure slider.

It can be useful to use the dynamic range feature in a camera, as both the electronic viewfinder and the embedded JPEG will show a "corrected" image with midtone/highlight detail. The allows for easier framing and culling of images.

Examples of camera implementations include: Fujifilm DR100/DR200/DR400 ("dynamic range"), Sony DRO (Dynamic Range Optimizer), Canon ALO, and Nikon Active D-Lighting.

Describe the solution you'd like
Similar to the "EXIF exposure bias" feature, darktable should examine the EXIF data to determine when an image was photographed with a "dynamic range" mode. It should then offer the option to increase the exposure appropriately. In a scene-referred workflow, this provides an adequate starting point for further work.

There would need to be another button in the exposure iop, similar to "compensate exposure bias". Or "compensate exposure bias" could beome a combobox to compensate for either/both/none of exposure bias or dynamic range. There should be a preference to always apply the appropriate dynamic range correction to newly imported images.

Alternatives
There could be a separate module which handles this, perhaps by adjusting exposure and applying a further correction to shadows or highlights. This would privilege automatic behavior over careful tuning by the user. It is also overlap with tools in the current scene-referred workflow.

I believe that some years ago people would craft different basecurves depending on the dynamic range mode. This were never entirely adequate, perhaps due to limitations of display-referred workflow.

It could be possible to simply implement presets depending on dynamic range mode, if the EXIF tags were accessible. This would clutter the preset interface, though.

This feature could be combined with "EXIF exposure bias" when the image file is read, in order to produce one compensation. The problem is that exposure bias is stored in the DB but not the sidecar. Extant images with exposure bias applied would change if EXIF data is re-read from disk (e.g. if the database were lost but the sidecar remained).

Additional context
For Fujifilm EXIFs, we want to look at the RawExposureBias tag (0x9650). Unfortunately, this tags is a 4-byte ratio of two signed shorts which exiv2 currently (v0.27.3) can't read. Luckily, there is a DevelopmentDynamicRange tag which maps to RawExposureBias:

DevelopmentDynamicRange RawExposureBias
100 DR -0.7 EV
200 DR -1.7 EV
400 DR -2.7 EV

I have checked this on a Fujifilm X100S and X100V.

DevelopmentDynamicRange is only present when the DynamicRangeSetting tag 0x1402 is Manual/Raw (0x0001). When it is Auto (0x0000), the equivalent data is in AutoDynamicRange tag 0x140b. But exiv2 currently can't read that tag either.

Hence it is possible to make a workable Fujifilm implementation when DR is set manually but not automatically. Any further work would require a patch to exiv2 to both teach it about new tags and to read a new data type.

I have not looked into this for any other camera.

Here is a proof of concept:

modified   src/common/exif.cc
@@ -776,6 +776,34 @@ static bool _exif_decode_exif_data(dt_image_t *img, Exiv2::ExifData &exifData)
       img->exif_exposure_bias = pos->toFloat();
     }
 
+    // DR shift contributes to exposure bias
+    // FIXME: store this separately from exposure bias to allow specific compensation
+    // FIXME: Sony DRO, Canon ALO, Nikon Active D-Light are similar -- handle these
+    if(FIND_EXIF_TAG("Exif.Fujifilm.DevelopmentDynamicRange"))
+    {
+      const int dr = pos->toLong();
+      float ev = NAN;
+      switch(pos->toLong())  // verbose version of -0.7f-log2f(n/100.0f)
+      {
+	case 100:
+	  ev = -0.7f;
+	  break;
+	case 200:
+	  ev = -1.7f;
+	  break;
+	case 400:
+	  ev = -2.7f;
+	  break;
+        default:
+	  printf("Unknown value for `Exif.Fujifilm.DevelopmentDynamicRange': %d\n", dr);
+      }
+      if(!isnan(ev))
+      {
+	// FIXME: is ExposureBiasValue and RawExposureBias ever both present?
+	img->exif_exposure_bias = isnan(img->exif_exposure_bias) ? ev : img->exif_exposure_bias + ev;
+      }
+    }
+
     /* Read aperture */
     if((pos = Exiv2::fNumber(exifData)) != exifData.end() && pos->size())
     {

Further work would require adding new dynamic_range_exposure_bias to the DB, metadata, variables, and exposure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions