• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

digikam

adjustcurvestool.cpp

Go to the documentation of this file.
00001 /* ============================================================
00002  *
00003  * This file is a part of digiKam project
00004  * http://www.digikam.org
00005  *
00006  * Date        : 2004-12-01
00007  * Description : image histogram adjust curves.
00008  *
00009  * Copyright (C) 2004-2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
00010  *
00011  * This program is free software; you can redistribute it
00012  * and/or modify it under the terms of the GNU General
00013  * Public License as published by the Free Software Foundation;
00014  * either version 2, or (at your option)
00015  * any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  * GNU General Public License for more details.
00021  *
00022  * ============================================================ */
00023 
00024 
00025 #include "adjustcurvestool.moc"
00026 
00027 // C++ includes
00028 
00029 #include <cmath>
00030 
00031 // Qt includes
00032 
00033 #include <QColor>
00034 #include <QFrame>
00035 #include <QGridLayout>
00036 #include <QGroupBox>
00037 #include <QHBoxLayout>
00038 #include <QLabel>
00039 #include <QPainter>
00040 #include <QPixmap>
00041 #include <QPushButton>
00042 #include <QSpinBox>
00043 #include <QTimer>
00044 #include <QToolButton>
00045 
00046 // KDE includes
00047 
00048 #include <kaboutdata.h>
00049 #include <kapplication.h>
00050 #include <kcombobox.h>
00051 #include <kconfig.h>
00052 #include <kcursor.h>
00053 #include <kfiledialog.h>
00054 #include <kglobal.h>
00055 #include <kglobalsettings.h>
00056 #include <khelpmenu.h>
00057 #include <kicon.h>
00058 #include <kiconloader.h>
00059 #include <klocale.h>
00060 #include <kmenu.h>
00061 #include <kmessagebox.h>
00062 #include <kselector.h>
00063 #include <kstandarddirs.h>
00064 
00065 // Local includes
00066 
00067 #include "colorgradientwidget.h"
00068 #include "curveswidget.h"
00069 #include "curvesbox.h"
00070 #include "daboutdata.h"
00071 #include "dimg.h"
00072 #include "dimgimagefilters.h"
00073 #include "editortoolsettings.h"
00074 #include "histogrambox.h"
00075 #include "histogramwidget.h"
00076 #include "imagecurves.h"
00077 #include "imagehistogram.h"
00078 #include "imageiface.h"
00079 #include "imagewidget.h"
00080 #include "version.h"
00081 
00082 using namespace Digikam;
00083 
00084 namespace DigikamAdjustCurvesImagesPlugin
00085 {
00086 
00087 class AdjustCurvesToolPriv
00088 {
00089 public:
00090 
00091     AdjustCurvesToolPriv() :
00092         configGroupName("adjustcurves Tool"),
00093         configHistogramChannelEntry("Histogram Channel"),
00094         configHistogramScaleEntry("Histogram Scale"),
00095         configCurveEntry("AdjustCurves"),
00096         destinationPreviewData(0),
00097         histoSegments(0),
00098         currentPreviewMode(0),
00099         channelCB(0),
00100         curvesBox(0),
00101         previewWidget(0),
00102         originalImage(0),
00103         gboxSettings(0)
00104         {}
00105 
00106     const QString        configGroupName;
00107     const QString        configHistogramChannelEntry;
00108     const QString        configHistogramScaleEntry;
00109     const QString        configCurveEntry;
00110 
00111     uchar*               destinationPreviewData;
00112 
00113     int                  histoSegments;
00114     int                  currentPreviewMode;
00115 
00116     KComboBox*           channelCB;
00117 
00118     CurvesBox*           curvesBox;
00119     ImageWidget*         previewWidget;
00120 
00121     DImg*                originalImage;
00122 
00123     EditorToolSettings*  gboxSettings;
00124 };
00125 
00126 AdjustCurvesTool::AdjustCurvesTool(QObject* parent)
00127                 : EditorTool(parent),
00128                   d(new AdjustCurvesToolPriv)
00129 {
00130     setObjectName("adjustcurves");
00131     setToolName(i18n("Adjust Curves"));
00132     setToolIcon(SmallIcon("adjustcurves"));
00133 
00134     d->destinationPreviewData = 0;
00135 
00136     ImageIface iface(0, 0);
00137     d->originalImage = iface.getOriginalImg();
00138 
00139     d->histoSegments = d->originalImage->sixteenBit() ? 65535 : 255;
00140 
00141     // -------------------------------------------------------------
00142 
00143     d->previewWidget = new ImageWidget("adjustcurves Tool", 0,
00144                                       i18n("This is the image's curve-adjustments preview. "
00145                                            "You can pick a spot on the image "
00146                                            "to see the corresponding level in the histogram."));
00147     setToolView(d->previewWidget);
00148 
00149     // -------------------------------------------------------------
00150 
00151     d->gboxSettings = new EditorToolSettings;
00152     d->gboxSettings->setButtons(EditorToolSettings::Default|
00153                                 EditorToolSettings::Load|
00154                                 EditorToolSettings::SaveAs|
00155                                 EditorToolSettings::Ok|
00156                                 EditorToolSettings::Cancel);
00157 
00158     d->gboxSettings->setTools( EditorToolSettings::Histogram);
00159     d->gboxSettings->setHistogramType(Digikam::LRGBA);
00160 
00161     d->gboxSettings->histogramBox()->histogram()->setWhatsThis(i18n("Here you can see the target preview "
00162                                                   "image histogram drawing of the selected image "
00163                                                   "channel. This one is re-computed at any curves "
00164                                                   "settings changes."));
00165 
00166     // we don't need to use the Gradient widget in this tool
00167     d->gboxSettings->histogramBox()->setGradientVisible(false);
00168 
00169     // -------------------------------------------------------------
00170 
00171     d->curvesBox = new CurvesBox(256, 256, d->originalImage->bits(), d->originalImage->width(),
00172                                  d->originalImage->height(), d->originalImage->sixteenBit());
00173 
00174     d->curvesBox->enableGradients(true);
00175     d->curvesBox->enableControlWidgets(true);
00176 
00177     // -------------------------------------------------------------
00178 
00179     QGridLayout* mainLayout = new QGridLayout();
00180     mainLayout->addWidget(d->curvesBox, 0, 0, 1, 1);
00181     mainLayout->setRowStretch(1, 10);
00182     mainLayout->setMargin(0);
00183     mainLayout->setSpacing(d->gboxSettings->spacingHint());
00184     d->gboxSettings->plainPage()->setLayout(mainLayout);
00185 
00186     // -------------------------------------------------------------
00187 
00188     setToolSettings(d->gboxSettings);
00189     init();
00190 
00191     // -------------------------------------------------------------
00192 
00193     connect(d->curvesBox, SIGNAL(signalCurvesChanged()),
00194             this, SLOT(slotTimer()));
00195 
00196     connect(d->previewWidget, SIGNAL(spotPositionChangedFromOriginal( const Digikam::DColor &, const QPoint & )),
00197             this, SLOT(slotSpotColorChanged( const Digikam::DColor & )));
00198 
00199     connect(d->previewWidget, SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const QPoint & )),
00200             this, SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
00201 
00202     connect(d->previewWidget, SIGNAL(signalResized()),
00203             this, SLOT(slotEffect()));
00204 
00205     // -------------------------------------------------------------
00206     // Buttons slots.
00207 
00208     connect(d->curvesBox, SIGNAL(signalChannelReset(int)),
00209             this, SLOT(slotResetCurrentChannel()));
00210 //
00211     connect(d->curvesBox, SIGNAL(signalPickerChanged(int)),
00212             this, SLOT(slotPickerColorButtonActived()));
00213 }
00214 
00215 AdjustCurvesTool::~AdjustCurvesTool()
00216 {
00217     delete [] d->destinationPreviewData;
00218     delete d;
00219 }
00220 
00221 void AdjustCurvesTool::slotPickerColorButtonActived()
00222 {
00223     // Save previous rendering mode and toggle to original image.
00224     d->currentPreviewMode = d->previewWidget->getRenderingPreviewMode();
00225     d->previewWidget->setRenderingPreviewMode(ImageGuideWidget::PreviewOriginalImage);
00226 }
00227 
00228 void AdjustCurvesTool::slotSpotColorChanged(const DColor& color)
00229 {
00230     DColor sc = color;
00231 
00232     switch (d->curvesBox->picker())
00233     {
00234         case CurvesBox::BlackTonal:
00235         {
00236             // Black tonal curves point.
00237             d->curvesBox->curves()->setCurvePoint(LuminosityChannel, 1,
00238                     QPoint(qMax(qMax(sc.red(), sc.green()), sc.blue()), 42*d->histoSegments/256));
00239             d->curvesBox->curves()->setCurvePoint(RedChannel, 1, QPoint(sc.red(), 42*d->histoSegments/256));
00240             d->curvesBox->curves()->setCurvePoint(GreenChannel, 1, QPoint(sc.green(), 42*d->histoSegments/256));
00241             d->curvesBox->curves()->setCurvePoint(BlueChannel, 1, QPoint(sc.blue(), 42*d->histoSegments/256));
00242             d->curvesBox->resetPickers();
00243             break;
00244         }
00245         case CurvesBox::GrayTonal:
00246         {
00247             // Gray tonal curves point.
00248             d->curvesBox->curves()->setCurvePoint(LuminosityChannel, 8,
00249                     QPoint(qMax(qMax(sc.red(), sc.green()), sc.blue()), 128*d->histoSegments/256));
00250             d->curvesBox->curves()->setCurvePoint(RedChannel, 8, QPoint(sc.red(), 128*d->histoSegments/256));
00251             d->curvesBox->curves()->setCurvePoint(GreenChannel, 8, QPoint(sc.green(), 128*d->histoSegments/256));
00252             d->curvesBox->curves()->setCurvePoint(BlueChannel, 8, QPoint(sc.blue(), 128*d->histoSegments/256));
00253             d->curvesBox->resetPickers();
00254             break;
00255         }
00256         case CurvesBox::WhiteTonal:
00257         {
00258             // White tonal curves point.
00259             d->curvesBox->curves()->setCurvePoint(LuminosityChannel, 15,
00260                     QPoint(qMax(qMax(sc.red(), sc.green()), sc.blue()), 213*d->histoSegments/256));
00261             d->curvesBox->curves()->setCurvePoint(RedChannel, 15, QPoint(sc.red(), 213*d->histoSegments/256));
00262             d->curvesBox->curves()->setCurvePoint(GreenChannel, 15, QPoint(sc.green(), 213*d->histoSegments/256));
00263             d->curvesBox->curves()->setCurvePoint(BlueChannel, 15, QPoint(sc.blue(), 213*d->histoSegments/256));
00264             d->curvesBox->resetPickers();
00265             break;
00266         }
00267         default:
00268         {
00269             d->curvesBox->setCurveGuide(color);
00270             return;
00271         }
00272     }
00273 
00274     // Calculate Red, green, blue curves.
00275 
00276     for (int i = LuminosityChannel ; i <= BlueChannel ; ++i)
00277        d->curvesBox->curves()->curvesCalculateCurve(i);
00278 
00279     d->curvesBox->repaint();
00280 
00281     // restore previous rendering mode.
00282     d->previewWidget->setRenderingPreviewMode(d->currentPreviewMode);
00283 
00284     slotEffect();
00285 }
00286 
00287 void AdjustCurvesTool::slotColorSelectedFromTarget( const DColor& color )
00288 {
00289     d->gboxSettings->histogramBox()->histogram()->setHistogramGuideByColor(color);
00290 }
00291 
00292 void AdjustCurvesTool::slotResetCurrentChannel()
00293 {
00294     slotEffect();
00295     d->gboxSettings->histogramBox()->histogram()->reset();
00296 }
00297 
00298 void AdjustCurvesTool::slotEffect()
00299 {
00300     ImageIface* iface = d->previewWidget->imageIface();
00301     uchar *orgData    = iface->getPreviewImage();
00302     int w             = iface->previewWidth();
00303     int h             = iface->previewHeight();
00304     bool sb           = iface->previewSixteenBit();
00305 
00306     // Create the new empty destination image data space.
00307     d->gboxSettings->histogramBox()->histogram()->stopHistogramComputation();
00308 
00309     if (d->destinationPreviewData)
00310        delete [] d->destinationPreviewData;
00311 
00312     d->destinationPreviewData = new uchar[w*h*(sb ? 8 : 4)];
00313 
00314     // Calculate the LUT to apply on the image.
00315     d->curvesBox->curves()->curvesLutSetup(AlphaChannel);
00316 
00317     // Apply the LUT to the image.
00318     d->curvesBox->curves()->curvesLutProcess(orgData, d->destinationPreviewData, w, h);
00319 
00320     iface->putPreviewImage(d->destinationPreviewData);
00321     d->previewWidget->updatePreview();
00322 
00323     // Update histogram.
00324     d->gboxSettings->histogramBox()->histogram()->updateData(d->destinationPreviewData, w, h, sb, 0, 0, 0, false);
00325     delete [] orgData;
00326 }
00327 
00328 void AdjustCurvesTool::finalRendering()
00329 {
00330     kapp->setOverrideCursor( Qt::WaitCursor );
00331 
00332     ImageIface* iface = d->previewWidget->imageIface();
00333     uchar *orgData    = iface->getOriginalImage();
00334     int w             = iface->originalWidth();
00335     int h             = iface->originalHeight();
00336     bool sb           = iface->originalSixteenBit();
00337 
00338     // Create the new empty destination image data space.
00339     uchar* desData = new uchar[w*h*(sb ? 8 : 4)];
00340 
00341     // Calculate the LUT to apply on the image.
00342     d->curvesBox->curves()->curvesLutSetup(AlphaChannel);
00343 
00344     // Apply the LUT to the image.
00345     d->curvesBox->curves()->curvesLutProcess(orgData, desData, w, h);
00346 
00347     iface->putOriginalImage(i18n("Adjust Curve"), desData);
00348     kapp->restoreOverrideCursor();
00349 
00350     delete [] orgData;
00351     delete [] desData;
00352 }
00353 
00354 void AdjustCurvesTool::slotChannelChanged()
00355 {
00356     d->curvesBox->setChannel(d->gboxSettings->histogramBox()->channel());
00357     d->gboxSettings->histogramBox()->slotChannelChanged();
00358 }
00359 
00360 void AdjustCurvesTool::slotScaleChanged()
00361 {
00362     d->curvesBox->setScale(d->gboxSettings->histogramBox()->scale());
00363 }
00364 
00365 void AdjustCurvesTool::readSettings()
00366 {
00367     KSharedConfig::Ptr config = KGlobal::config();
00368     KConfigGroup group = config->group(d->configGroupName);
00369 
00370     d->curvesBox->reset();
00371     d->curvesBox->readCurveSettings(group, d->configCurveEntry);
00372 
00373     // we need to call the set methods here, otherwise the curve will not be updated correctly
00374     d->gboxSettings->histogramBox()->setChannel(group.readEntry(d->configHistogramChannelEntry,
00375                     (int)LuminosityChannel));
00376     d->gboxSettings->histogramBox()->setScale((HistogramScale)group.readEntry(d->configHistogramScaleEntry,
00377                     (int)LogScaleHistogram));
00378 
00379     d->curvesBox->setScale(d->gboxSettings->histogramBox()->scale());
00380     d->curvesBox->setChannel(d->gboxSettings->histogramBox()->channel());
00381     d->curvesBox->update();
00382 
00383     slotEffect();
00384 }
00385 
00386 void AdjustCurvesTool::writeSettings()
00387 {
00388     KSharedConfig::Ptr config = KGlobal::config();
00389     KConfigGroup group = config->group(d->configGroupName);
00390     group.writeEntry(d->configHistogramChannelEntry, d->gboxSettings->histogramBox()->channel());
00391     group.writeEntry(d->configHistogramScaleEntry,   (int)d->gboxSettings->histogramBox()->scale());
00392 
00393     d->curvesBox->writeCurveSettings(group, d->configCurveEntry);
00394     d->previewWidget->writeSettings();
00395 
00396     config->sync();
00397 }
00398 
00399 void AdjustCurvesTool::slotResetSettings()
00400 {
00401     d->curvesBox->resetChannels();
00402     d->curvesBox->resetPickers();
00403     d->gboxSettings->histogramBox()->histogram()->reset();
00404 
00405     slotEffect();
00406 }
00407 
00408 void AdjustCurvesTool::slotLoadSettings()
00409 {
00410     KUrl loadCurvesFile;
00411 
00412     loadCurvesFile = KFileDialog::getOpenUrl(KGlobalSettings::documentPath(),
00413                                              QString( "*" ), kapp->activeWindow(),
00414                                              QString( i18n("Select Gimp Curves File to Load")) );
00415     if ( loadCurvesFile.isEmpty() )
00416        return;
00417 
00418     if ( d->curvesBox->curves()->loadCurvesFromGimpCurvesFile( loadCurvesFile ) == false )
00419     {
00420         KMessageBox::error(kapp->activeWindow(),
00421                            i18n("Cannot load from the Gimp curves text file."));
00422         return;
00423     }
00424 
00425     // Refresh the current curves config.
00426     slotChannelChanged();
00427     slotEffect();
00428 }
00429 
00430 void AdjustCurvesTool::slotSaveAsSettings()
00431 {
00432     KUrl saveCurvesFile;
00433 
00434     saveCurvesFile = KFileDialog::getSaveUrl(KGlobalSettings::documentPath(),
00435                                              QString( "*" ), kapp->activeWindow(),
00436                                              QString( i18n("Gimp Curves File to Save")) );
00437     if ( saveCurvesFile.isEmpty() )
00438        return;
00439 
00440     if ( d->curvesBox->curves()->saveCurvesToGimpCurvesFile( saveCurvesFile ) == false )
00441     {
00442         KMessageBox::error(kapp->activeWindow(),
00443                            i18n("Cannot save to the Gimp curves text file."));
00444         return;
00445     }
00446 
00447     // Refresh the current curves config.
00448     slotChannelChanged();
00449 }
00450 
00451 }  // namespace DigikamAdjustCurvesImagesPlugin

digikam

Skip menu "digikam"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • digikam
Generated for API Reference by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal