Add Sony metadata lens correction
This commit is contained in:
parent
f64ad13363
commit
27dc084e81
@ -24,6 +24,31 @@
|
||||
namespace rtengine
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
/* interpolateLinearSpline does a simple linear spline interpolation. Values
|
||||
* outside the external knots will return the value of the nearest knot without
|
||||
* any additional interpolation. */
|
||||
double interpolateLinearSpline(const std::vector<double> &xi, const std::vector<double> &yi, double x)
|
||||
{
|
||||
if (x < xi[0]) {
|
||||
return yi[0];
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < xi.size(); i++) {
|
||||
if (x >= xi[i - 1] && x <= xi[i]) {
|
||||
double dydx = (yi[i] - yi[i - 1]) / (xi[i] - xi[i - 1]);
|
||||
|
||||
return yi[i - 1] + (x - xi[i - 1]) * dydx;
|
||||
}
|
||||
}
|
||||
|
||||
return yi[yi.size() - 1];
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
CenterRadiusMetadataLensCorrection::CenterRadiusMetadataLensCorrection(const FramesMetaData *meta) :
|
||||
swap_xy(false)
|
||||
{
|
||||
@ -132,9 +157,133 @@ void CenterRadiusMetadataLensCorrection::processVignette3Channels(int width, int
|
||||
return processVignetteNChannels(width, height, rawData, 3);
|
||||
}
|
||||
|
||||
/* Fuji, Sony, Olympus metadata handling and algorithms adapted from
|
||||
* - src/iop/lens.cc
|
||||
* - src/common/exif.cc
|
||||
* in darktable 4.6 */
|
||||
/*
|
||||
This file is part of darktable,
|
||||
Copyright (C) 2019-2024 darktable developers.
|
||||
|
||||
darktable is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
darktable is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with darktable. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
class SonyMetadataLensCorrection : public CenterRadiusMetadataLensCorrection
|
||||
{
|
||||
public:
|
||||
SonyMetadataLensCorrection(const FramesMetaData *meta) :
|
||||
CenterRadiusMetadataLensCorrection(meta)
|
||||
{
|
||||
parse();
|
||||
setup();
|
||||
}
|
||||
|
||||
private:
|
||||
int nc;
|
||||
std::array<short, 16> distortion;
|
||||
std::array<short, 16> ca_r;
|
||||
std::array<short, 16> ca_b;
|
||||
std::array<short, 16> vignetting;
|
||||
|
||||
std::vector<double> knots;
|
||||
std::vector<double> dist;
|
||||
std::array<std::vector<double>, 3> ca;
|
||||
std::vector<double> vig;
|
||||
|
||||
void parse()
|
||||
{
|
||||
if (Exiv2::versionNumber() < EXIV2_MAKE_VERSION(0, 27, 4)) {
|
||||
throw std::runtime_error("cannot get Sony correction data, too old exiv2 version " + Exiv2::versionString());
|
||||
}
|
||||
|
||||
auto &exif = metadata.exifData();
|
||||
|
||||
auto posd = exif.findKey(Exiv2::ExifKey("Exif.SubImage1.DistortionCorrParams"));
|
||||
auto posc = exif.findKey(Exiv2::ExifKey("Exif.SubImage1.ChromaticAberrationCorrParams"));
|
||||
auto posv = exif.findKey(Exiv2::ExifKey("Exif.SubImage1.VignettingCorrParams"));
|
||||
|
||||
/* Sony metadata corrections parameters define some splines with N knots */
|
||||
if (posd == exif.end() || posc == exif.end() || posv == exif.end()) {
|
||||
throw std::runtime_error("cannot get Sony correction data");
|
||||
}
|
||||
|
||||
const int nc = to_long(posd);
|
||||
if (nc <= 16 && 2 * nc == to_long(posc) && nc == to_long(posv)) {
|
||||
this->nc = nc;
|
||||
for (int i = 0; i < nc; i++) {
|
||||
distortion[i] = to_long(posd, i + 1);
|
||||
ca_r[i] = to_long(posc, i + 1);
|
||||
ca_b[i] = to_long(posc, nc + i + 1);
|
||||
vignetting[i] = to_long(posv, i + 1);
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("cannot get Sony correction data");
|
||||
}
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
knots.resize(nc);
|
||||
dist.resize(nc);
|
||||
vig.resize(nc);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
ca[i].resize(nc);
|
||||
}
|
||||
|
||||
for (int i = 0; i < this->nc; i++) {
|
||||
knots[i] = (i + 0.5) / (nc - 1);
|
||||
|
||||
dist[i] = distortion[i] * powf(2, -14) + 1;
|
||||
|
||||
ca[0][i] = ca[1][i] = ca[2][i] = 1.f;
|
||||
ca[0][i] *= ca_r[i] * powf(2, -21) + 1;
|
||||
ca[2][i] *= ca_b[i] * powf(2, -21) + 1;
|
||||
|
||||
vig[i] = 1 / powf(2, 0.5f - powf(2, vignetting[i] * powf(2, -13) - 1));
|
||||
}
|
||||
}
|
||||
|
||||
double distortionCorrectionFactor(double rout) const override
|
||||
{
|
||||
return interpolateLinearSpline(knots, dist, rout);
|
||||
}
|
||||
|
||||
double caCorrectionFactor(double rout, int channel) const override
|
||||
{
|
||||
return interpolateLinearSpline(knots, ca[channel], rout);
|
||||
}
|
||||
|
||||
double distortionAndCACorrectionFactor(double rout, int channel) const override
|
||||
{
|
||||
return distortionCorrectionFactor(rout) * caCorrectionFactor(rout, channel);
|
||||
}
|
||||
|
||||
double vignettingCorrectionFactor(double r) const override
|
||||
{
|
||||
return interpolateLinearSpline(knots, vig, r);
|
||||
}
|
||||
|
||||
bool hasDistortionCorrection() const override { return true; }
|
||||
bool hasVignettingCorrection() const override { return true; }
|
||||
bool hasCACorrection() const override { return true; }
|
||||
};
|
||||
|
||||
std::unique_ptr<MetadataLensCorrection> MetadataLensCorrectionFinder::findCorrection(const FramesMetaData *meta)
|
||||
{
|
||||
static const std::unordered_set<std::string> makers = {};
|
||||
static const std::unordered_set<std::string> makers = {
|
||||
"SONY",
|
||||
};
|
||||
|
||||
std::string make = Glib::ustring(meta->getMake()).uppercase();
|
||||
|
||||
@ -144,6 +293,18 @@ std::unique_ptr<MetadataLensCorrection> MetadataLensCorrectionFinder::findCorrec
|
||||
|
||||
std::unique_ptr<MetadataLensCorrection> correction;
|
||||
|
||||
try {
|
||||
if (make == "SONY") {
|
||||
correction.reset(new SonyMetadataLensCorrection(meta));
|
||||
}
|
||||
} catch (std::exception &exc) {
|
||||
if (settings->verbose) {
|
||||
std::cerr << "error parsing lens metadata: " << exc.what() << std::endl;
|
||||
}
|
||||
|
||||
correction.reset(nullptr);
|
||||
}
|
||||
|
||||
return correction;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user