Skip to content

DNG Opcodelist3 Gainmap for DJI Drones#20467

Draft
hennikul wants to merge 2 commits intodarktable-org:masterfrom
hennikul:dji-gainmap-rgb
Draft

DNG Opcodelist3 Gainmap for DJI Drones#20467
hennikul wants to merge 2 commits intodarktable-org:masterfrom
hennikul:dji-gainmap-rgb

Conversation

@hennikul
Copy link

@hennikul hennikul commented Mar 8, 2026

This PR implements support for Opcodelist 3, which is needed to get gainmap support for DNG files from drones like DJI Mini 4 Pro. Without the Gainmap, the colors are only correct in the center of the photos, and shift towards the edges, the same goes for exposure.

There is a closed issue that explains this problem, and it also includes hints about how to solve it:
#13319

This implementation was done using Claude Sonnet, and giving it the hints from the above issue and iterating until I got correct colors in DNG files from my DJI Mini 4 Pro Drone inside of Darktable.

hennikul and others added 2 commits March 8, 2026 09:05
1. Extract _parse_and_append_gain_map() from the OpcodeList2 handler to
   eliminate duplication and centralise GainMap parsing with debug logging
2. Log parsed GainMap fields (dimensions, planes, pitch) via DT_DEBUG_IMAGEIO
3. Update dng_gain_maps comment in dt_image_t to mention OpcodeList3
4. Add OpcodeList3 OPCODE_ID_GAINMAP handler using the new helper so that
   DNG files embedding GainMaps in OpcodeList3 (e.g. DJI cameras) are
   loaded into image->dng_gain_maps for downstream processing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DJI cameras (e.g. Mavic 3 Pro) embed a single RGB GainMap in DNG
OpcodeList3 with planes=3, map_planes=3, row_pitch=1, col_pitch=1
instead of four per-Bayer-filter maps. The existing _check_gain_maps()
only handled the 4-map Bayer format so DJI files got no flat-field
correction.

1. Add _check_gain_map_rgb() to validate the single-map RGB format
2. Add logging to _check_gain_maps() rejection paths via DT_DEBUG_IMAGEIO
3. Apply RGB gainmap in process() using bilinear interpolation with
   FC()-based Bayer filter mapping (bl_to_plane[4]) to select the
   correct R/G/B plane per pixel
4. Add OpenCL kernels rawprepare_1f_gainmap_rgb and
   rawprepare_1f_unnormalized_gainmap_rgb in basic.cl, uploading
   each plane as a separate float image2d_t for GPU sampling
5. Update commit_params() to try _check_gain_map_rgb() as a fallback
   when the 4-map Bayer path is unavailable
6. Update reload_defaults() and gui_update() to show the Flat field
   control when either gainmap format is present

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@hennikul hennikul changed the title Dji gainmap rgb DNG Opcodelist3 Gainmap for DJI Drones Mar 8, 2026
@jenshannoschwalm
Copy link
Collaborator

Just had a first look, not bad :-)

  1. Can't test, could you provide some images?
  2. looks ok according to dng specs
  3. The selected gain-map area seems ok to me. Not sure though about the map-id to rgb channel conversion. Did you test changing the offsets in rawprepare module (you have to enable in preferences plugins/darkroom/rawprepare/allow_editing_crop=TRUE to do so) try combinations of even/odds for the offsets as those change the cfa filter pattern, choosing very large values should allow you to test if the chosen area is correct.

@hennikul
Copy link
Author

I have added a couple of examples here: https://gofile.me/5vUdR/4hvHNPRYi

Both are DNG files and corresponding JPG straight from the Drone (ie. taken in JPEG+RAW mode). The JPG has the gainmap applied correctly by the Drone.

One is a photo taken above a fjord in Norway, the other is a photo of a white paper. I tried to use the white photo as a kind of reference to adjust using masks and color calibration modules before this fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants