3rd-party lens automatic detection

I made a lens profile for a 3rd-party Z-mount lens and manually modified Darktable’s lens profile data in share\lensfun\version_1\misc.xml.

Since Darktable wasn’t detecting the model automatically, I searched and found how to create a .exiv2 file in my home directory with the identification numbers.

In this case, for a Voigtländer APO-LANTHAR 35mm F2 Aspherical II, I got:

[nikon]
0=35mm f/2

and it works fine. EDIT: “0” and “253” work fine, apparently. Before, I used “1 0” which worked, but it doesn’t any more (??).

I’m just wondering if I missed something: could I add more elements into the XML for that specific lens so that Darktable, once it integrates the lensfun data in a future version, can automatically recognize the lens without that exiv2 custom profile? I can still modify the data I submitted in their GitHub, but I didn’t see anything in the other 3rd-party lenses, so I suspect it’s a limitation of Darktable; other tools like Affinity don’t need that extra step from every single user (and I don’t see any relevant element in lensfun’s format for the model numbers).

For now, the XML looks like this:

    <lens>
        <maker>Voigtländer</maker>
        <model>35mm f/2</model>
        <model lang="en">APO-LANTHAR 35mm F2 Aspherical II</model>
        <mount>Nikon Z</mount>
        <cropfactor>1</cropfactor>
        <calibration>
            <!-- Taken with Nikon Z6III -->
            <distortion model="ptlens" focal="35" a="0.00726" b="-0.01914" c="0.0101"/>
            <tca model="poly3" focal="35.0" vr="1.0000325" vb="0.9999729" />
            <vignetting model="pa" focal="35.0" aperture="2.0" distance="0.27" k1="-1.7274801" k2="1.4821616" k3="-0.5357087" />
            <vignetting model="pa" focal="35.0" aperture="2.0" distance="0.54" k1="-2.1529816" k2="2.1936554" k3="-0.8936036" />
            <vignetting model="pa" focal="35.0" aperture="2.0" distance="1.62" k1="-2.3381563" k2="2.5067040" k3="-1.0497600" />
            <vignetting model="pa" focal="35.0" aperture="2.0" distance="1000" k1="-2.4054764" k2="2.6108750" k3="-1.0973622" />
            <vignetting model="pa" focal="35.0" aperture="2.8" distance="0.27" k1="-0.4931862" k2="-0.3903400" k3="0.2860779" />
            <vignetting model="pa" focal="35.0" aperture="2.8" distance="0.54" k1="-0.5818163" k2="-0.5645652" k3="0.4422908" />
            <vignetting model="pa" focal="35.0" aperture="2.8" distance="1.62" k1="-0.6329567" k2="-0.6647739" k3="0.5480756" />
            <vignetting model="pa" focal="35.0" aperture="2.8" distance="1000" k1="-0.6536585" k2="-0.7188463" k3="0.6043772" />
            <vignetting model="pa" focal="35.0" aperture="4.0" distance="0.27" k1="-0.5839239" k2="0.0348811" k3="0.0656375" />
            <vignetting model="pa" focal="35.0" aperture="4.0" distance="0.54" k1="-0.7391125" k2="0.1372117" k3="0.0234026" />
            <vignetting model="pa" focal="35.0" aperture="4.0" distance="1.62" k1="-0.8256081" k2="0.2102259" k3="-0.0122386" />
            <vignetting model="pa" focal="35.0" aperture="4.0" distance="1000" k1="-0.8589557" k2="0.2228163" k3="-0.0119729" />
            <vignetting model="pa" focal="35.0" aperture="5.6" distance="0.27" k1="-0.5812536" k2="0.0279456" k3="0.0705040" />
            <vignetting model="pa" focal="35.0" aperture="5.6" distance="0.54" k1="-0.7175983" k2="0.0628979" k3="0.0875625" />
            <vignetting model="pa" focal="35.0" aperture="5.6" distance="1.62" k1="-0.7939760" k2="0.0946543" k3="0.0903589" />
            <vignetting model="pa" focal="35.0" aperture="5.6" distance="1000" k1="-0.8303944" k2="0.1121402" k3="0.0904709" />
            <vignetting model="pa" focal="35.0" aperture="16.0" distance="0.27" k1="-0.6030442" k2="0.0509183" k3="0.0586593" />
            <vignetting model="pa" focal="35.0" aperture="16.0" distance="0.54" k1="-0.7165359" k2="0.0224849" k3="0.1161671" />
            <vignetting model="pa" focal="35.0" aperture="16.0" distance="1.62" k1="-0.7985310" k2="0.0598960" k3="0.1186587" />
            <vignetting model="pa" focal="35.0" aperture="16.0" distance="1000" k1="-0.8312505" k2="0.0598966" k3="0.1325040" />
         </calibration>
    </lens>

It’s a little strange that Darktable can’t use <model> to identify the lens when the numbers didn’t match anything.

From your Lensfun github issue, it looks like you have converted your original NEF files to DNG? When you do that, it looks like the original Nikon MakerNotes get “lost”, and darktable lens detection logic no longer works as intended. The “35 mm f/2” string might be inserted by Adobe…

I thought it was Exiv2 that did the lens recognition, and darktable just passed on the string from Exiv2 to lensfun (which is why the .exiv2 file works). I.e. darktable itself doesn’t do anything with lens ID numbers or <model> strings.

As for the different behaviour of Affinity, I’m not sure if they (are allowed to) use the lensfun and/or exiv2 libraries, being closed source…

That’s about 95% of the story, yes. In reality, it’s not that straightforward and dt sets some priority and chooses what specific Exiv2 tags to query depending on camera body vendor etc. Historically, and unfortunately, there are always corner cases… I.e. here’s the current snippet for Nikons.

The “Exif.NikonLd4” in that snippet is a reference to the “makernote” data?

Yes.

I found something interesting.

When I open a NEF file:

  • In the image information panel, it only shows “lens: 253”, even with the modified .exiv2 file, and if I don’t give the information above in that .exiv2 file, it shows “253” in the lens model dropdown, too (that I have then to manually set to the correct vendor and model).

When I open a DNG file (converted from a NEF), after removing the .exiv2 file:

  • Darktable shows “lens: 35mm f/2” in the information panel, and it auto-detects the correct lens and model.

I’ve tried both with new images (no corresponding .nksc stack files) after removing the .exiv2, to make sure, and it was consistent.

So it seems Darktable doesn’t decode the lens type in NEF files for 3rd-party lenses—I never had any problem for Nikkor lenses, though I haven’t tested that thoroughly. But with DNG files converted from the NEF, it’s fine. And the “Lens Model” tag is exactly the same in both cases.

I’ll check again later, in case I missed something.

Those NEFs are not HE/HE*, by the way.

3rd party lens vendors and exiv2 are a problem, often because the lens ID is just an integer, and a bunch of 3rd party manufacturers use an integer that is already used for a first party lens.

But exiv2 is decoding it, the value is 253. You need to map that on to a name that matches whatever is in lensfun using the .exiv2 file.

I confirm the difference I saw earlier.

I extracted “Lens Model” and “Lens Info”, both are strictly identical in NEF and DNG files (both of the same photograph, the DNG made by Adobe DNG Converter).

I need to put what I quoted above, so “1 0” and not “253”. EDIT: now, it works, despite my testing it several times yesterday. Go figure.

It’s really just an issue with NEF files, so if I have the time, I’ll try to see with some tool that uses the exiv2 library (assuming exiftool doesn’t, or not the same version). Chances are it doesn’t decode those fields correctly in NEFs.

I’d disregard the DNG stuff, that’s probably different.

What camera is the NEF from?

You also have the model element twice in your lensfun XML file, which I assume is not good.

What do you mean?

Nikon Z6III, though I don’t think it’s relevant.

No, it’s standard. The first one is for real identification from the exif and the 2nd with the locale information is for user display. If you look at the lensfun database, you’ll see that many lenses are defined like that, if not all of them.

I see the EXIF data is encoded in a completely different format in the NEF files than in the DNG files (where tags and values can even be seen in ASCII directly in the file).

However, when I check with an exiv2 binary (version 0.28.5), the info is the same in both files:

507:bin $ ./exiv2 -pe DSC_1956.NEF |grep Model
Exif.Image.Model                             Ascii      11  NIKON Z6_3
Exif.Photo.LensModel                         Ascii      65  35mm f/2
508:bin $ ./exiv2 -pe DSC_1956.DNG |grep Model
Error: Directory Nikon1 with 25665 entries considered invalid; not read.
Exif.Image.Model                             Ascii      11  NIKON Z6_3
Exif.Photo.LensModel                         Ascii       9  35mm f/2
Exif.Image.UniqueCameraModel                 Ascii      12  Nikon Z 6 3

I don’t know which version Darktable is using.
Rawtherapee doesn’t have the same problem; it auto-detects the lens model in both files, without the .exiv2 profile in my home directory (I modified both programs’ misc.xml file by adding the same lens model as above, so they both have the same information and the same raw files).

EDIT: I replaced Darktable’s libexiv2.dll by Rawtherapee’s one, but it doesn’t change the problem. I think I’ll just report that as a bug.

Ah, the solution was right in front of me. Thanks, @kmilos!

The NEF file has indeed a Exif.NikonLd4.LensID = 1 0, and Darktable pounces on that instead of using Exif.Photo.LensModel = 35mm f/2, which is “last resort”, thus failing to identify the lens in the lensfun database.

There’s a long discussion about that (I think) in that feature request:

I’ll read it later; it’s been a long day.

That post above is a little different because the user modifies the EXIF before using Darktable.

I filed in an issue. The model detection is apparently not an easy task.