Skip to content

[feat] lens correction#255

Open
antond-weta wants to merge 3 commits intoAcademySoftwareFoundation:mainfrom
antond-weta:lens2
Open

[feat] lens correction#255
antond-weta wants to merge 3 commits intoAcademySoftwareFoundation:mainfrom
antond-weta:lens2

Conversation

@antond-weta
Copy link
Contributor

Description

Implements lens correction functionality

Tests

Checklist:

  • I have read the contribution guidelines.
  • I have updated the documentation, if applicable. (Check if there is no
    need to update the documentation, for example if this is a bug fix that
    doesn't change the API.)
  • I have ensured that the change is tested somewhere in the testsuite
    (adding new test cases if necessary).
  • My code follows the prevailing code style of this project. If I haven't
    already run clang-format before submitting, I definitely will look at the CI
    test that runs clang-format and fix anything that it highlights as being
    nonconforming.

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
@codecov-commenter
Copy link

codecov-commenter commented Mar 4, 2026

Codecov Report

❌ Patch coverage is 92.22720% with 52 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.51%. Comparing base (4053a2c) to head (5ded3c4).

Files with missing lines Patch % Lines
src/rawtoaces_util/image_converter.cpp 80.32% 49 Missing ⚠️
src/rawtoaces_util/lens_correction.cpp 99.32% 2 Missing ⚠️
src/rawtoaces_util/exiftool.cpp 98.73% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #255      +/-   ##
==========================================
+ Coverage   90.22%   90.51%   +0.29%     
==========================================
  Files          15       17       +2     
  Lines        2680     3312     +632     
  Branches      405      498      +93     
==========================================
+ Hits         2418     2998     +580     
- Misses        262      314      +52     
Files with missing lines Coverage Δ
include/rawtoaces/image_converter.h 100.00% <100.00%> (ø)
src/rawtoaces/main.cpp 100.00% <100.00%> (ø)
src/rawtoaces_core/rawtoaces_core.cpp 99.63% <100.00%> (ø)
src/rawtoaces_util/cache_base.h 100.00% <100.00%> (ø)
src/rawtoaces_util/colour_transforms.cpp 100.00% <ø> (ø)
src/rawtoaces_util/lens_correction_cache.cpp 100.00% <100.00%> (ø)
src/rawtoaces_util/exiftool.cpp 99.21% <98.73%> (-0.79%) ⬇️
src/rawtoaces_util/lens_correction.cpp 99.32% <99.32%> (ø)
src/rawtoaces_util/image_converter.cpp 77.44% <80.32%> (+0.61%) ⬆️

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4053a2c...5ded3c4. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
exiftool_to_oiio = { { "Make", { "cameraMake", false } },
{ "Model", { "cameraModel", false } },
{ "LensID", { "lensModel", false } },
{ "LensModel", { "lensModel", false } },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious why we removing it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exiftool seems to be inconsistent with this field for some cameras. This makes it difficult to decide what to do when both LensID and LensModel are present and hold different value.

BTW I'm expecting this code to be tweaked a fair bit as this functionality gets more use. Collecting metadata from raw images is always a balancing act.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've refactored that further to make it a bit more robust. The lensModel thingy is back!

fetch_lens_parameter(
lens_make,
src_spec,
"lenMake",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lensMake

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

auto cam = cameras[0];

const lfLens **lenses =
Database->FindLenses( cam, NULL, lens_model.c_str() );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should lens_make be used here instead of NULL?

const char* lens_make_ptr =
    lens_make.empty() ? nullptr : lens_make.c_str();

const lfLens** lenses =
    Database->FindLenses(cam, lens_make_ptr, lens_model.c_str());

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

{
if ( !apply_aberration_map(
dst,
src,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at each state of these three calls we give dst and src where is src is seem to be the same object that came in originally. The only reason it works if because our internal called uses same object for dst and src. But this is public API and hence we should handle the case where these two are not the same.

if ( &dst != &src )
   dst.copy( src );
...
            if ( !apply_vignette_map(
                     dst,
                     dst,
...
            if ( !apply_aberration_map(
                     dst,
                     dst,
...
            if ( !apply_distortion_map(
                     dst,
                     dst,

or some more robust way.

Also, it seems like you have tests void test_apply_lens_correction() where those two are not the same, so am I correct assuming the result would be only distortion map applied?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch! fixed.

Copy link
Contributor

@soswow soswow Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure. I think I understand what LLM is saying, but I rather paste it as-is so nothing is lost in translation:

[image_converter.h (line 374)] documents apply_lens_correction(dst, src) as supporting distinct buffers, but the implementation starts with src_ptr = &src and only switches to dst after a prior stage succeeds [image_converter.cpp (line 1636)]. If the first enabled stage is distortion or aberration, the lower-level code depends on dst being already initialized: distortion takes its temp spec from dst_buffer.spec() [lens_correction.cpp (line 461)], and aberration actually warps from dst_buffer instead of src_buffer [lens_correction.cpp (line 600)], [lens_correction.cpp (line 612)]. Existing success-path tests are in-place for distortion/aberration [testLensCorrection.cpp (line 261)], [testLensCorrection.cpp (line 317)], while the only out-of-place success test is vignetting [testLensCorrection.cpp (line 466)].

Suggested fix: initialize a working buffer from src when dst != src, chain every enabled stage against the previous output, and add explicit out-of-place success tests for distortion-only, aberration-only, and combined correction.

last_error_message );
}

OIIO::ParamValueList options;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

.value(
"CropApplicationError",
ImageConverter::Status::CropApplicationError )
.value( "WriteError", ImageConverter::Status::WriteError )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to add

.value(
            "DatabaseNotFound", ImageConverter::Status::DatabaseNotFound )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


rawtoaces \
--lens-correction a \
--require-lens correction \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
--require-lens correction \
--require-lens-correction \

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

--custom-lens-model "RF 24-105mm F4L IS USM" \
--custom-aperture 4.0 \
--custom-focal-length 35.0 \
--custom-focus_distance 240.0 \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
--custom-focus_distance 240.0 \
--custom-focus-distance 240.0 \

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment on lines +392 to +393
converter.settings.custom_lens_make = "custom_lens_model"
assert converter.settings.custom_lens_make == "custom_lens_model"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
converter.settings.custom_lens_make = "custom_lens_model"
assert converter.settings.custom_lens_make == "custom_lens_model"
converter.settings.custom_lens_model = "custom_lens_model"
assert converter.settings.custom_lens_model == "custom_lens_model"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Signed-off-by: Anton Dukhovnikov <antond@wetafx.co.nz>
@soswow
Copy link
Contributor

soswow commented Mar 10, 2026

Do we want maybe separate status LensCorrectionError for when correction failed?

ImageConverter::Settings::LensCorrectionType::None )
{
if ( settings.custom_lens_model.empty() )
keys_to_check.push_back( "lensModel" );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shuould we be doing same for lensMake?

{ "aperture", "FNumber" },
{ "focalLength", "FocalLength" }
{ "cameraMake", "Make" }, { "cameraModel", "Model" },
{ "lensModel", "LensModel" }, { "lensID", "LensID" },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need mapping for lensMake?

{ "Missing the camera model name in the file metadata.",
" You can provide a custom value using the --custom-camera-model "
"parameter." },
{ "Missing the lens model name in the file metadata.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actual message is "Missing the <property> info in the file metadata."

"Distortion",
ImageConverter::Settings::LensCorrectionType::Distortion )
.value(
"Vignetting",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also None

enum class LensCorrectionType
        {
            None       = 0,
            Aberration = 1 << 0,
            Distortion = 1 << 1,
            Vignetting = 1 << 2
        };

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.

3 participants