------------------------------------------------------------------------ r778164 | abaecker | 2008-02-22 18:52:23 +0100 (Fri, 22 Feb 2008) | 8 lines More flexible WB adjustment during raw decoding (many thanks to Guillaume Castagnino for the patch). Note that a current libkdcraw is needed as this had to be changed. CCBUGS: 142055 TODO:KDE4PORT ------------------------------------------------------------------------ Index: digikam/imageplugins/whitebalance/imageeffect_whitebalance.cpp =================================================================== --- digikam/imageplugins/whitebalance/imageeffect_whitebalance.cpp (revision 778163) +++ digikam/imageplugins/whitebalance/imageeffect_whitebalance.cpp (revision 778164) @@ -7,7 +7,8 @@ * Description : a digiKam image editor plugin to correct * image white balance * - * Copyright (C) 2005-2007 by Gilles Caulier + * Copyright (C) 2005-2008 by Gilles Caulier + * Copyright (C) 2008 by Guillaume Castagnino * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General @@ -191,7 +192,7 @@ ImageEffect_WhiteBalance::ImageEffect_Wh m_adjTemperatureLabel = new QLabel(i18n("Adjustment:"), gboxSettings); m_temperatureInput = new KDoubleNumInput(gboxSettings); m_temperatureInput->setPrecision(1); - m_temperatureInput->setRange(2200.0, 7000.0, 10.0, true); + m_temperatureInput->setRange(2000.0, 12000.0, 10.0, true); QWhatsThis::add( m_temperatureInput, i18n("

Set here the white balance color temperature in Kelvin.")); m_temperaturePresetLabel = new QLabel(i18n("Preset:"), gboxSettings); @@ -268,7 +269,7 @@ ImageEffect_WhiteBalance::ImageEffect_Wh m_greenLabel = new QLabel(i18n("Green:"), gboxSettings); m_greenInput = new KDoubleNumInput(gboxSettings); m_greenInput->setPrecision(2); - m_greenInput->setRange(1.0, 2.5, 0.01, true); + m_greenInput->setRange(0.2, 2.5, 0.01, true); QWhatsThis::add(m_greenInput, i18n("

Set here the green component to set magenta color " "cast removal level.")); @@ -633,7 +634,7 @@ void ImageEffect_WhiteBalance::slotEffec m_destinationPreviewData = new uchar[w*h*(sb ? 8 : 4)]; - double temperature = m_temperatureInput->value()/1000.0; + double temperature = m_temperatureInput->value(); double dark = m_darkInput->value(); double black = m_blackInput->value(); double mainExposure = m_mainExposureInput->value(); @@ -666,7 +667,7 @@ void ImageEffect_WhiteBalance::finalRend int h = iface->originalHeight(); bool sb = iface->originalSixteenBit(); - double temperature = m_temperatureInput->value()/1000.0; + double temperature = m_temperatureInput->value(); double dark = m_darkInput->value(); double black = m_blackInput->value(); double mainExposure = m_mainExposureInput->value(); @@ -698,16 +699,16 @@ void ImageEffect_WhiteBalance::resetValu m_greenInput->blockSignals(true); m_temperaturePresetCB->blockSignals(true); - // Neutral color temperature settings. + // Neutral color temperature settings is D65 m_darkInput->setValue(0.5); m_blackInput->setValue(0.0); m_mainExposureInput->setValue(0.0); m_fineExposureInput->setValue(0.0); m_gammaInput->setValue(1.0); m_saturationInput->setValue(1.0); - m_greenInput->setValue(1.2); - m_temperaturePresetCB->setCurrentItem(Neutral); - slotTemperaturePresetChanged(Neutral); + m_greenInput->setValue(1.0); + m_temperaturePresetCB->setCurrentItem(DaylightD65); + slotTemperaturePresetChanged(DaylightD65); m_previewWidget->resetSpotPosition(); m_channelCB->setCurrentItem(LuminosityChannel); @@ -739,8 +740,8 @@ void ImageEffect_WhiteBalance::readUserS m_fineExposureInput->setValue(config->readDoubleNumEntry("FineExposure", 0.0)); m_gammaInput->setValue(config->readDoubleNumEntry("Gamma", 1.0)); m_saturationInput->setValue(config->readDoubleNumEntry("Saturation", 1.0)); - m_greenInput->setValue(config->readDoubleNumEntry("Green", 1.2)); - m_temperatureInput->setValue(config->readDoubleNumEntry("Temperature", 4750.0)); + m_greenInput->setValue(config->readDoubleNumEntry("Green", 1.0)); + m_temperatureInput->setValue(config->readDoubleNumEntry("Temperature", 6500.0)); slotTemperatureChanged(m_temperatureInput->value()); slotChannelChanged(m_channelCB->currentItem()); slotScaleChanged(m_scaleBG->selectedId()); Index: digikam/imageplugins/whitebalance/imageeffect_whitebalance.h =================================================================== --- digikam/imageplugins/whitebalance/imageeffect_whitebalance.h (revision 778163) +++ digikam/imageplugins/whitebalance/imageeffect_whitebalance.h (revision 778164) @@ -7,7 +7,8 @@ * Description : a digiKam image editor plugin to correct * image white balance * - * Copyright (C) 2005-2007 by Gilles Caulier + * Copyright (C) 2005-2008 by Gilles Caulier + * Copyright (C) 2008 by Guillaume Castagnino * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General @@ -22,7 +23,6 @@ * * ============================================================ */ - #ifndef IMAGEEFFECT_WHITEBALANCE_H #define IMAGEEFFECT_WHITEBALANCE_H --- digikam/libs/whitebalance/whitebalance.cpp (revision 778163) +++ digikam/libs/whitebalance/whitebalance.cpp (revision 778164) @@ -6,7 +6,8 @@ * Date : 2007-16-01 * Description : white balance color correction. * - * Copyright (C) 2007 by Gilles Caulier + * Copyright (C) 2007-2008 by Gilles Caulier + * Copyright (C) 2008 by Guillaume Castagnino * * Some parts are inspired from RawPhoto implementation copyrighted * 2004-2005 by Pawel T. Jochym @@ -39,7 +40,6 @@ #include "ddebug.h" #include "imagehistogram.h" -#include "blackbody.h" #include "whitebalance.h" namespace Digikam @@ -69,8 +69,8 @@ public: exposition = 0.0; gamma = 1.0; saturation = 1.0; - green = 1.2; - temperature = 4.750; + green = 1.0; + temperature = 6500.0; } bool clipSat; @@ -127,7 +127,7 @@ void WhiteBalance::whiteBalance(uchar *d if (d->clipSat) d->mg = 1.0; setLUTv(); setRGBmult(); - + // Apply White balance adjustments. adjustWhiteBalance(data, width, height, sixteenBit); } @@ -136,41 +136,33 @@ void WhiteBalance::autoWBAdjustementFrom { // Calculate Temperature and Green component from color picked. - register int l, r, m; - double sR, sG, sB, mRB, t; + double tmin, tmax, mBR; + float mr, mg, mb; - t = QMAX( QMAX(tc.red(), tc.green()), tc.blue()); - sR = tc.red() / t; - sG = tc.green() / t; - sB = tc.blue() / t; - mRB = sR / sB; - - DDebug() << "Sums: R:" << sR << " G:" << sG << " B:" << sB << endl; - - l = 0; - r = sizeof(blackBodyWhiteBalance)/(sizeof(float)*3); - m = (r + l) / 2; + DDebug() << "Sums: R:" << tc.red() << " G:" << tc.green() << " B:" << tc.blue() << endl; - for (l = 0, r = sizeof(blackBodyWhiteBalance)/(sizeof(float)*3), m = (l+r)/2 ; r-l > 1 ; m = (l+r)/2) + /* 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 + */ + tmin = 2000.0; + tmax = 12000.0; + mBR = (double)tc.blue() / (double)tc.red(); + green = 1.0; + for (temperature = (tmin+tmax)/2; tmax-tmin > 10; temperature = (tmin+tmax)/2) { - if (blackBodyWhiteBalance[m][0]/blackBodyWhiteBalance[m][2] > mRB) - l = m; + DDebug() << "Intermediate Temperature (K):" << temperature << endl; + setRGBmult(temperature, green, mr, mg, mb); + if (mr/mb > mBR) + tmax = temperature; else - r = m; - - DDebug() << "L,M,R: " << l << " " << m << " " << r - << " blackBodyWhiteBalance[m]=:" << blackBodyWhiteBalance[m][0]/blackBodyWhiteBalance[m][2] - << endl; + tmin = temperature; } - - DDebug() << "Temperature (K):" << m*10.0+2000.0 << endl; - - t = (blackBodyWhiteBalance[m][1]/blackBodyWhiteBalance[m][0]) / (sG/sR); + // Calculate the green level to neutralize picture + green = (mr / mg) / ((double)tc.green() / (double)tc.red()); - DDebug() << "Green component:" << t << endl; - - temperature = m*10.0+2000.0; - green = t; + DDebug() << "Temperature (K):" << temperature << endl; + DDebug() << "Green component:" << green << endl; } void WhiteBalance::autoExposureAdjustement(uchar* data, int width, int height, bool sb, @@ -207,25 +199,73 @@ void WhiteBalance::autoExposureAdjusteme delete histogram; } -void WhiteBalance::setRGBmult() +void WhiteBalance::setRGBmult(double &temperature, double &green, float &mr, float &mg, float &mb) { - int t; float mi; + double xD, yD, X, Y, Z; - if ( d->temperature > 7.0 ) d->temperature = 7.0; + if ( temperature > 12000 ) temperature = 12000.0; - t = (int)(d->temperature * 100.0 - 200.0); - d->mr = 1.0 / blackBodyWhiteBalance[t][0]; - d->mg = 1.0 / blackBodyWhiteBalance[t][1]; - d->mb = 1.0 / blackBodyWhiteBalance[t][2]; - d->mg *= d->green; + /* Here starts the code picked from ufraw (0.12.1) + to convert Temperature + green multiplier to RGB multipliers + */ + /* Convert between Temperature and RGB. + * Base on information from http://www.brucelindbloom.com/ + * The fit for D-illuminant between 4000K and 12000K are from CIE + * The generalization to 2000K < T < 4000K and the blackbody fits + * are my own and should be taken with a grain of salt. + */ + const double XYZ_to_RGB[3][3] = { + { 3.24071, -0.969258, 0.0556352 }, + {-1.53726, 1.87599, -0.203996 }, + {-0.498571, 0.0415557, 1.05707 } }; + // Fit for CIE Daylight illuminant + if (temperature <= 4000) + { + xD = 0.27475e9/(temperature*temperature*temperature) + - 0.98598e6/(temperature*temperature) + + 1.17444e3/temperature + 0.145986; + } + else if (temperature <= 7000) + { + xD = -4.6070e9/(temperature*temperature*temperature) + + 2.9678e6/(temperature*temperature) + + 0.09911e3/temperature + 0.244063; + } + else + { + xD = -2.0064e9/(temperature*temperature*temperature) + + 1.9018e6/(temperature*temperature) + + 0.24748e3/temperature + 0.237040; + } + yD = -3*xD*xD + 2.87*xD - 0.275; + + X = xD/yD; + Y = 1; + Z = (1-xD-yD)/yD; + mr = X*XYZ_to_RGB[0][0] + Y*XYZ_to_RGB[1][0] + Z*XYZ_to_RGB[2][0]; + mg = X*XYZ_to_RGB[0][1] + Y*XYZ_to_RGB[1][1] + Z*XYZ_to_RGB[2][1]; + mb = X*XYZ_to_RGB[0][2] + Y*XYZ_to_RGB[1][2] + Z*XYZ_to_RGB[2][2]; + /* End of the code picked to ufraw + */ + + // Apply green multiplier + mg = mg / green; + + mr = 1.0 / mr; + mg = 1.0 / mg; + mb = 1.0 / mb; // Normalize to at least 1.0, so we are not dimming colors only bumping. - mi = QMIN(d->mr, d->mg); - mi = QMIN(mi, d->mb); - d->mr /= mi; - d->mg /= mi; - d->mb /= mi; + mi = QMIN(mr, QMIN(mg, mb)); + mr /= mi; + mg /= mi; + mb /= mi; +} + +void WhiteBalance::setRGBmult() +{ + setRGBmult(d->temperature, d->green, d->mr, d->mg, d->mb); } void WhiteBalance::setLUTv() Index: digikam/libs/whitebalance/whitebalance.h =================================================================== --- digikam/libs/whitebalance/whitebalance.h (revision 778163) +++ digikam/libs/whitebalance/whitebalance.h (revision 778164) @@ -6,7 +6,8 @@ * Date : 2007-16-01 * Description : white balance color correction. * - * Copyright (C) 2007 by Gilles Caulier + * Copyright (C) 2007-2008 by Gilles Caulier + * Copyright (C) 2008 by Guillaume Castagnino * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General @@ -45,7 +46,7 @@ public: void whiteBalance(uchar *data, int width, int height, bool sixteenBit, double black=0.0, double exposition=0.0, - double temperature=4.750, double green=1.2, double dark=0.5, + double temperature=6500.0, double green=1.0, double dark=0.5, double gamma=1.0, double saturation=1.0); static void autoExposureAdjustement(uchar* data, int width, int height, bool sb, @@ -56,6 +57,7 @@ public: private: void setRGBmult(); + static void setRGBmult(double &temperature, double &green, float &mr, float &mg, float &mb); void setLUTv(); void adjustWhiteBalance(uchar *data, int width, int height, bool sixteenBit); inline unsigned short pixelColor(int colorMult, int index, int value); Index: digikam/utilities/setup/setupdcraw.cpp =================================================================== --- digikam/utilities/setup/setupdcraw.cpp (revision 778163) +++ digikam/utilities/setup/setupdcraw.cpp (revision 778164) @@ -6,7 +6,7 @@ * Date : 2007-02-06 * Description : setup RAW decoding settings. * - * Copyright (C) 2007 by Gilles Caulier + * Copyright (C) 2007-2008 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General @@ -89,8 +89,9 @@ void SetupDcraw::applySettings() KConfig* config = kapp->config(); config->setGroup("ImageViewer Settings"); config->writeEntry("SixteenBitsImage", d->dcrawSettings->sixteenBits()); - config->writeEntry("CameraColorBalance", d->dcrawSettings->useCameraWB()); - config->writeEntry("AutomaticColorBalance", d->dcrawSettings->useAutoColorBalance()); + config->writeEntry("WhiteBalance", d->dcrawSettings->whiteBalance()); + config->writeEntry("CustomWhiteBalance", d->dcrawSettings->customWhiteBalance()); + config->writeEntry("CustomWhiteBalanceGreen", d->dcrawSettings->customWhiteBalanceGreen()); config->writeEntry("RGBInterpolate4Colors", d->dcrawSettings->useFourColor()); config->writeEntry("DontStretchPixels", d->dcrawSettings->useDontStretchPixels()); config->writeEntry("EnableNoiseReduction", d->dcrawSettings->useNoiseReduction()); @@ -116,8 +117,11 @@ void SetupDcraw::readSettings() d->dcrawSettings->setcaBlueMultiplier(config->readDoubleNumEntry("caBlueMultiplier", 1.0)); d->dcrawSettings->setDontStretchPixels(config->readBoolEntry("DontStretchPixels", false)); d->dcrawSettings->setUnclipColor(config->readNumEntry("UnclipColors", 0)); - d->dcrawSettings->setCameraWB(config->readBoolEntry("CameraColorBalance", true)); - d->dcrawSettings->setAutoColorBalance(config->readBoolEntry("AutomaticColorBalance", true)); + d->dcrawSettings->setWhiteBalance((KDcrawIface::RawDecodingSettings::WhiteBalance) + config->readNumEntry("WhiteBalance", + KDcrawIface::RawDecodingSettings::CAMERA)); + d->dcrawSettings->setCustomWhiteBalance(config->readNumEntry("CustomWhiteBalance", 6500)); + d->dcrawSettings->setCustomWhiteBalanceGreen(config->readDoubleNumEntry("CustomWhiteBalanceGreen", 1.0)); d->dcrawSettings->setFourColor(config->readBoolEntry("RGBInterpolate4Colors", false)); d->dcrawSettings->setQuality((KDcrawIface::RawDecodingSettings::DecodingQuality) config->readNumEntry("RAWQuality", Index: digikam/utilities/setup/setupdcraw.h =================================================================== --- digikam/utilities/setup/setupdcraw.h (revision 778163) +++ digikam/utilities/setup/setupdcraw.h (revision 778164) @@ -6,7 +6,7 @@ * Date : 2007-02-06 * Description : setup RAW decoding settings. * - * Copyright (C) 2007 by Gilles Caulier + * Copyright (C) 2007-2008 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General Index: digikam/utilities/imageeditor/editor/editorwindow.cpp =================================================================== --- digikam/utilities/imageeditor/editor/editorwindow.cpp (revision 778163) +++ digikam/utilities/imageeditor/editor/editorwindow.cpp (revision 778164) @@ -894,10 +894,12 @@ void EditorWindow::applyStandardSettings m_IOFileSettings->rawDecodingSettings.outputColorSpace = KDcrawIface::RawDecodingSettings::SRGB; m_IOFileSettings->rawDecodingSettings.sixteenBitsImage = config->readBoolEntry("SixteenBitsImage", false); - m_IOFileSettings->rawDecodingSettings.automaticColorBalance = config->readBoolEntry("AutomaticColorBalance", true); - m_IOFileSettings->rawDecodingSettings.cameraColorBalance = config->readBoolEntry("CameraColorBalance", true); + m_IOFileSettings->rawDecodingSettings.whiteBalance = (KDcrawIface::RawDecodingSettings::WhiteBalance)config->readNumEntry("WhiteBalance", + KDcrawIface::RawDecodingSettings::CAMERA); + m_IOFileSettings->rawDecodingSettings.customWhiteBalance = config->readNumEntry("CustomWhiteBalance", 6500); + m_IOFileSettings->rawDecodingSettings.customWhiteBalanceGreen = config->readDoubleNumEntry("CustomWhiteBalanceGreen", 1.0); m_IOFileSettings->rawDecodingSettings.RGBInterpolate4Colors = config->readBoolEntry("RGBInterpolate4Colors", false); - m_IOFileSettings->rawDecodingSettings.DontStretchPixels = config->readBoolEntry("DontStretchPixels", false); + m_IOFileSettings->rawDecodingSettings.DontStretchPixels = config->readBoolEntry("DontStretchPixels", false); m_IOFileSettings->rawDecodingSettings.enableNoiseReduction = config->readBoolEntry("EnableNoiseReduction", false); m_IOFileSettings->rawDecodingSettings.unclipColors = config->readNumEntry("UnclipColors", 0); m_IOFileSettings->rawDecodingSettings.RAWQuality = (KDcrawIface::RawDecodingSettings::DecodingQuality)config->readNumEntry("RAWQuality",