diff --git a/core/dplugins/generic/tools/panorama/tasks/optimisationtask.cpp b/core/dplugins/generic/tools/panorama/tasks/optimisationtask.cpp index 74a74ec83e..cdd7ba280b 100644 --- a/core/dplugins/generic/tools/panorama/tasks/optimisationtask.cpp +++ b/core/dplugins/generic/tools/panorama/tasks/optimisationtask.cpp @@ -1,79 +1,82 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2016 by Benjamin Girault * * This program 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 2, or (at your option) any later version. * * This program 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. * * ============================================================ */ #include "optimisationtask.h" // Qt includes #include namespace DigikamGenericPanoramaPlugin { OptimisationTask::OptimisationTask(const QString& workDirPath, const QUrl& input, QUrl& autoOptimiserPtoUrl, bool levelHorizon, bool gPano, const QString& autooptimiserPath) : CommandTask(PANO_OPTIMIZE, workDirPath, autooptimiserPath), autoOptimiserPtoUrl(autoOptimiserPtoUrl), ptoUrl(input), levelHorizon(levelHorizon), buildGPano(gPano) { } OptimisationTask::~OptimisationTask() { } void OptimisationTask::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*) { autoOptimiserPtoUrl = tmpDir; autoOptimiserPtoUrl.setPath(autoOptimiserPtoUrl.path() + QLatin1String("auto_op_pano.pto")); QStringList args; args << QLatin1String("-am"); if (levelHorizon) args << QLatin1String("-l"); - if (!buildGPano) - args << QLatin1String("-s"); - + // This parameter changes the projection type + // See also Bug 346053 and Bug 416492 +/* + if (buildGPano) + args << QLatin1String("-s"); +*/ args << QLatin1String("-o"); args << autoOptimiserPtoUrl.toLocalFile(); args << ptoUrl.toLocalFile(); runProcess(args); // AutoOptimiser does not return an error code when something went wrong... QFile ptoOutput(autoOptimiserPtoUrl.toLocalFile()); if (!ptoOutput.exists()) { successFlag = false; errString = getProcessError(); } printDebug(QLatin1String("autooptimiser")); } } // namespace DigikamGenericPanoramaPlugin diff --git a/core/libs/dimg/filters/wb/wbfilter.cpp b/core/libs/dimg/filters/wb/wbfilter.cpp index e264e3f76e..5a8a696d8e 100644 --- a/core/libs/dimg/filters/wb/wbfilter.cpp +++ b/core/libs/dimg/filters/wb/wbfilter.cpp @@ -1,410 +1,413 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2007-16-01 * Description : white balance color correction. * * Copyright (C) 2007-2020 by Gilles Caulier * Copyright (C) 2008 by Guillaume Castagnino * Copyright (C) 2010 by Martin Klapetek * * This program 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 2, or (at your option) * any later version. * * This program 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. * * ============================================================ */ #include "wbfilter.h" // C++ includes #include #include // KDE includes #include // Local includes #include "dimg.h" #include "digikam_debug.h" #include "imagehistogram.h" namespace Digikam { class Q_DECL_HIDDEN WBFilter::Private { public: explicit Private() : BP(0), WP(0), rgbMax(0), mr(1.0), mg(1.0), mb(1.0) { for (int i = 0 ; i < 65536 ; ++i) { curve[i] = 0.0; } } int BP; int WP; uint rgbMax; double curve[65536]; double mr; double mg; double mb; }; WBFilter::WBFilter(QObject* const parent) : DImgThreadedFilter(parent), d(new Private) { initFilter(); } WBFilter::WBFilter(DImg* const orgImage, QObject* const parent, const WBContainer& settings) : DImgThreadedFilter(orgImage, parent, QLatin1String("WBFilter")), m_settings(settings), d(new Private) { initFilter(); } WBFilter::WBFilter(const WBContainer& settings, DImgThreadedFilter* const master, const DImg& orgImage, const DImg& destImage, int progressBegin, int progressEnd) : DImgThreadedFilter(master, orgImage, destImage, progressBegin, progressEnd, QLatin1String("WBFilter")), m_settings(settings), d(new Private) { filterImage(); } WBFilter::~WBFilter() { cancelFilter(); delete d; } QString WBFilter::DisplayableName() { return QString::fromUtf8(I18N_NOOP("White Balance Tool")); } void WBFilter::filterImage() { d->WP = m_orgImage.sixteenBit() ? 65536 : 256; d->rgbMax = m_orgImage.sixteenBit() ? 65536 : 256; // Set final lut. setLUTv(); setRGBmult(m_settings.temperature, m_settings.green, d->mr, d->mg, d->mb); qCDebug(DIGIKAM_DIMG_LOG) << "T(K):" << m_settings.temperature << "=> R:" << d->mr << " G:" << d->mg << " B:" << d->mb << " BP:" << d->BP << " WP:" << d->WP; // Apply White balance adjustments. adjustWhiteBalance(m_orgImage.bits(), m_orgImage.width(), m_orgImage.height(), m_orgImage.sixteenBit()); m_destImage = m_orgImage; } void WBFilter::autoWBAdjustementFromColor(const QColor& tc, double& temperature, double& green) { // Calculate Temperature and Green component from color picked. double mr = 0.0; double mg = 0.0; double mb = 0.0; qCDebug(DIGIKAM_DIMG_LOG) << "Sums: R:" << tc.red() << " G:" << tc.green() << " B:" << tc.blue(); /** * This is a dichotomic search based on Blue and Red layers ratio * to find the matching temperature * adapted from ufraw (0.12.1) RGB_to_Temperature */ double tmin = 2000.0; double tmax = 12000.0; double mBR = (double)tc.blue() / (double)tc.red(); green = 1.0; for (temperature = (tmin + tmax) / 2 ; tmax - tmin > 10 ; temperature = (tmin + tmax) / 2) { qCDebug(DIGIKAM_DIMG_LOG) << "Intermediate Temperature (K):" << temperature; setRGBmult(temperature, green, mr, mg, mb); if (mr / mb > mBR) { tmax = temperature; } else { tmin = temperature; } } // Calculate the green level to neutralize picture green = (mr / mg) / ((double)tc.green() / (double)tc.red()); qCDebug(DIGIKAM_DIMG_LOG) << "Temperature (K):" << temperature; qCDebug(DIGIKAM_DIMG_LOG) << "Green component:" << green; } void WBFilter::autoExposureAdjustement(const DImg* const img, double& black, double& expo) { // Create an histogram of original image. ImageHistogram* const histogram = new ImageHistogram(*img); histogram->calculate(); // Calculate optimal exposition and black level int i; double sum, stop; uint rgbMax = img->sixteenBit() ? 65536 : 256; // Cutoff at 0.5% of the histogram. stop = img->width() * img->height() / 200; for (i = rgbMax, sum = 0 ; (i >= 0) && (sum < stop) ; --i) { sum += histogram->getValue(LuminosityChannel, i); } expo = -log((double)(i + 1) / rgbMax) / log(2); qCDebug(DIGIKAM_DIMG_LOG) << "White level at:" << i; for (i = 1, sum = 0 ; (i < (int)rgbMax) && (sum < stop) ; ++i) { sum += histogram->getValue(LuminosityChannel, i); } black = (double)i / rgbMax; black /= 2; qCDebug(DIGIKAM_DIMG_LOG) << "Black:" << black << " Exposition:" << expo; delete histogram; } void WBFilter::setRGBmult(double& temperature, double& green, double& mr, double& mg, double& mb) { // Original implementation by Tanner Helland // http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/ double temp = temperature / 100.0; double mx; if (temp > 120.0) { temp = 120.0; } if (temp <= 66.0) { mr = 1.0; mg = temp; mg = 99.4708025861 * log(mg) - 161.1195681661; } else { mr = temp - 60.0; mr = 329.698727466 * pow(mr, -0.1332047592); mr = 1.0 / (1.0 / 255.0 * CLAMP(mr, 0.0, 255.0)); mg = temp - 60.0; mg = 288.1221695283 * pow(mg, -0.0755148492); } mg = 1.0 / 255.0 * CLAMP(mg, 0.0, 255.0); // Apply green multiplier mg = mg / green; mg = 1.0 / mg; if (temp >= 66.0) { mb = 1.0; } else { if (temp <= 19.0) { mb = 0.0; } else { mb = temp - 10.0; mb = 138.5177312231 * log(mb) - 305.0447927307; mb = 1.0 / (1.0 / 255.0 * CLAMP(mb, 0.0, 255.0)); } } // Calculate to an average of 1.0 mx = ((mr + mg + mb) / 3.0) - 0.01; mr /= mx; mg /= mx; mb /= mx; } void WBFilter::setLUTv() { double b = pow(2, m_settings.expositionMain + m_settings.expositionFine); d->BP = (uint)(d->rgbMax * m_settings.black); d->WP = (uint)(d->rgbMax / b); if (d->WP - d->BP < 1) { d->WP = d->BP + 1; } d->curve[0] = 0.0; // We will try to reproduce the same Gamma effect here than BCG tool. double gamma; if (m_settings.gamma >= 1.0) { gamma = 0.335 * (2.0 - m_settings.gamma) + 0.665; } else { gamma = 1.8 * (2.0 - m_settings.gamma) - 0.8; } for (int i = 1 ; i < (int)d->rgbMax ; ++i) { double x = (double)(i - d->BP) / (d->WP - d->BP); d->curve[i] = (i < d->BP) ? 0 : (d->rgbMax - 1) * pow((double)x, gamma); d->curve[i] *= (1 - m_settings.dark * exp(-x * x / 0.002)); d->curve[i] /= (double)i; } } void WBFilter::adjustWhiteBalance(uchar* const data, int width, int height, bool sixteenBit) { uint size = (uint)(width * height); uint j; int progress; + qCDebug(DIGIKAM_DIMG_LOG) << "DImg data:" << data << "Size:" + << size << "sixteen bit:" << sixteenBit; + if (!sixteenBit) // 8 bits image. { uchar red, green, blue; uchar* ptr = data; for (j = 0 ; runningFlag() && (j < size) ; ++j) { int idx, rv[3]; blue = ptr[0]; green = ptr[1]; red = ptr[2]; rv[0] = (int)(blue * d->mb); rv[1] = (int)(green * d->mg); rv[2] = (int)(red * d->mr); idx = qMax(rv[0], rv[1]); idx = qMax(idx, rv[2]); idx = qMin(idx, (int)d->rgbMax - 1); ptr[0] = (uchar)pixelColor(rv[0], idx); ptr[1] = (uchar)pixelColor(rv[1], idx); ptr[2] = (uchar)pixelColor(rv[2], idx); ptr += 4; progress = (int)(((double)j * 100.0) / size); if ((progress % 5) == 0) { postProgress(progress); } } } else // 16 bits image. { unsigned short red, green, blue; unsigned short* ptr = reinterpret_cast(data); for (j = 0 ; runningFlag() && (j < size) ; ++j) { int idx, rv[3]; blue = ptr[0]; green = ptr[1]; red = ptr[2]; rv[0] = (int)(blue * d->mb); rv[1] = (int)(green * d->mg); rv[2] = (int)(red * d->mr); idx = qMax(rv[0], rv[1]); idx = qMax(idx, rv[2]); idx = qMin(idx, (int)d->rgbMax - 1); ptr[0] = pixelColor(rv[0], idx); ptr[1] = pixelColor(rv[1], idx); ptr[2] = pixelColor(rv[2], idx); ptr += 4; progress = (int)(((double)j * 100.0) / size); if ((progress % 5) == 0) { postProgress(progress); } } } } unsigned short WBFilter::pixelColor(int colorMult, int index) { int r = (colorMult > (int)d->rgbMax) ? d->rgbMax : colorMult; int c = (index - m_settings.saturation * (index - r)) * d->curve[index]; return ((unsigned short)CLAMP(c, 0, (int)(d->rgbMax - 1))); } FilterAction WBFilter::filterAction() { FilterAction action(FilterIdentifier(), CurrentVersion()); action.setDisplayableName(DisplayableName()); m_settings.writeToFilterAction(action); return action; } void WBFilter::readParameters(const FilterAction& action) { m_settings = WBContainer::fromFilterAction(action); } } // namespace Digikam