summaryrefslogtreecommitdiffstats
path: root/src/libs/imageproperties/imagepropertiescolorstab.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/imageproperties/imagepropertiescolorstab.cpp')
-rw-r--r--src/libs/imageproperties/imagepropertiescolorstab.cpp799
1 files changed, 799 insertions, 0 deletions
diff --git a/src/libs/imageproperties/imagepropertiescolorstab.cpp b/src/libs/imageproperties/imagepropertiescolorstab.cpp
new file mode 100644
index 00000000..af85953b
--- /dev/null
+++ b/src/libs/imageproperties/imagepropertiescolorstab.cpp
@@ -0,0 +1,799 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-11-17
+ * Description : a tab to display colors information of images
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqspinbox.h>
+#include <tqcombobox.h>
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqpushbutton.h>
+#include <tqtooltip.h>
+#include <tqvbox.h>
+#include <tqscrollview.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <ksqueezedtextlabel.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kdialogbase.h>
+#include <kstandarddirs.h>
+#include <ktabwidget.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "imagehistogram.h"
+#include "histogramwidget.h"
+#include "colorgradientwidget.h"
+#include "navigatebarwidget.h"
+#include "sharedloadsavethread.h"
+#include "iccprofilewidget.h"
+#include "cietonguewidget.h"
+#include "imagepropertiescolorstab.h"
+#include "imagepropertiescolorstab.moc"
+
+namespace Digikam
+{
+
+class ImagePropertiesColorsTabPriv
+{
+public:
+
+ enum MetadataTab
+ {
+ HISTOGRAM=0,
+ ICCPROFILE
+ };
+
+ ImagePropertiesColorsTabPriv()
+ {
+ imageLoaderThread = 0;
+ tab = 0;
+ channelCB = 0;
+ colorsCB = 0;
+ renderingCB = 0;
+ scaleBG = 0;
+ regionBG = 0;
+ minInterv = 0;
+ maxInterv = 0;
+ labelMeanValue = 0;
+ labelPixelsValue = 0;
+ labelStdDevValue = 0;
+ labelCountValue = 0;
+ labelMedianValue = 0;
+ labelPercentileValue = 0;
+ labelColorDepth = 0;
+ labelAlphaChannel = 0;
+
+ iccProfileWidget = 0;
+ hGradient = 0;
+ histogramWidget = 0;
+ imageLoaderThread = 0;
+
+ inLoadingProcess = false;
+ }
+
+ bool inLoadingProcess;
+
+ TQComboBox *channelCB;
+ TQComboBox *colorsCB;
+ TQComboBox *renderingCB;
+
+ TQHButtonGroup *scaleBG;
+ TQHButtonGroup *regionBG;
+
+ TQSpinBox *minInterv;
+ TQSpinBox *maxInterv;
+
+ TQLabel *labelMeanValue;
+ TQLabel *labelPixelsValue;
+ TQLabel *labelStdDevValue;
+ TQLabel *labelCountValue;
+ TQLabel *labelMedianValue;
+ TQLabel *labelPercentileValue;
+ TQLabel *labelColorDepth;
+ TQLabel *labelAlphaChannel;
+
+ TQString currentFilePath;
+ LoadingDescription currentLoadingDescription;
+
+ TQRect selectionArea;
+
+ TQByteArray embedded_profile;
+
+ KTabWidget *tab;
+
+ DImg image;
+ DImg imageSelection;
+
+ ICCProfileWidget *iccProfileWidget;
+ ColorGradientWidget *hGradient;
+ HistogramWidget *histogramWidget;
+ SharedLoadSaveThread *imageLoaderThread;
+};
+
+ImagePropertiesColorsTab::ImagePropertiesColorsTab(TQWidget* parent, bool navBar)
+ : NavigateBarTab(parent)
+{
+ d = new ImagePropertiesColorsTabPriv;
+
+ setupNavigateBar(navBar);
+ d->tab = new KTabWidget(this);
+ m_navigateBarLayout->addWidget(d->tab);
+
+ // Histogram tab area -----------------------------------------------------
+
+ TQScrollView *sv = new TQScrollView(d->tab);
+ sv->viewport()->setBackgroundMode(TQt::PaletteBackground);
+ sv->setResizePolicy(TQScrollView::AutoOneFit);
+ sv->setFrameStyle(TQFrame::NoFrame);
+
+ TQWidget* histogramPage = new TQWidget(sv->viewport());
+ TQGridLayout *topLayout = new TQGridLayout(histogramPage, 8, 3,
+ KDialog::spacingHint(), KDialog::spacingHint());
+ sv->addChild(histogramPage);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), histogramPage);
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ d->channelCB = new TQComboBox( false, histogramPage );
+ d->channelCB->insertItem( i18n("Luminosity") );
+ d->channelCB->insertItem( i18n("Red") );
+ d->channelCB->insertItem( i18n("Green") );
+ d->channelCB->insertItem( i18n("Blue") );
+ d->channelCB->insertItem( i18n("Alpha") );
+ d->channelCB->insertItem( i18n("Colors") );
+ TQWhatsThis::add( d->channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: Display luminosity (perceived brightness) values.<p>"
+ "<b>Red</b>: Display the red image channel.<p>"
+ "<b>Green</b>: Display the green image channel.<p>"
+ "<b>Blue</b>: Display the blue image channel.<p>"
+ "<b>Alpha</b>: Display the alpha image channel. "
+ "This channel corresponds to the transparency value and "
+ "is supported by some image formats such as PNG or TIFF.<p>"
+ "<b>Colors</b>: Display all color channel values at the same time."));
+
+ d->scaleBG = new TQHButtonGroup(histogramPage);
+ d->scaleBG->setExclusive(true);
+ d->scaleBG->setFrameShape(TQFrame::NoFrame);
+ d->scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( d->scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal values are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal values are big; "
+ "if it is used, all values (small and large) will be visible on the "
+ "graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( d->scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ d->scaleBG->insert(linHistoButton, HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( d->scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ d->scaleBG->insert(logHistoButton, HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQLabel *label10 = new TQLabel(i18n("Colors:"), histogramPage);
+ label10->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ d->colorsCB = new TQComboBox( false, histogramPage );
+ d->colorsCB->insertItem( i18n("Red") );
+ d->colorsCB->insertItem( i18n("Green") );
+ d->colorsCB->insertItem( i18n("Blue") );
+ d->colorsCB->setEnabled( false );
+ TQWhatsThis::add( d->colorsCB, i18n("<p>Select the main color displayed with Colors Channel mode here:<p>"
+ "<b>Red</b>: Draw the red image channel in the foreground.<p>"
+ "<b>Green</b>: Draw the green image channel in the foreground.<p>"
+ "<b>Blue</b>: Draw the blue image channel in the foreground.<p>"));
+
+ d->regionBG = new TQHButtonGroup(histogramPage);
+ d->regionBG->setExclusive(true);
+ d->regionBG->setFrameShape(TQFrame::NoFrame);
+ d->regionBG->setInsideMargin( 0 );
+ d->regionBG->hide();
+ TQWhatsThis::add( d->regionBG, i18n("<p>Select from which region the histogram will be computed here:<p>"
+ "<b>Full Image</b>: Compute histogram using the full image.<p>"
+ "<b>Selection</b>: Compute histogram using the current image "
+ "selection."));
+
+ TQPushButton *fullImageButton = new TQPushButton( d->regionBG );
+ TQToolTip::add( fullImageButton, i18n( "<p>Full Image" ) );
+ d->regionBG->insert(fullImageButton, HistogramWidget::FullImageHistogram);
+ TDEGlobal::dirs()->addResourceType("image-full", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("image-full", "image-full.png");
+ fullImageButton->setPixmap( TQPixmap( directory + "image-full.png" ) );
+ fullImageButton->setToggleButton(true);
+
+ TQPushButton *SelectionImageButton = new TQPushButton( d->regionBG );
+ TQToolTip::add( SelectionImageButton, i18n( "<p>Selection" ) );
+ d->regionBG->insert(SelectionImageButton, HistogramWidget::ImageSelectionHistogram);
+ TDEGlobal::dirs()->addResourceType("image-selection", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("image-selection", "image-selection.png");
+ SelectionImageButton->setPixmap( TQPixmap( directory + "image-selection.png" ) );
+ SelectionImageButton->setToggleButton(true);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(histogramPage);
+ d->histogramWidget = new HistogramWidget(256, 140, histoBox);
+ TQWhatsThis::add( d->histogramWidget, i18n("<p>This is the histogram drawing of the "
+ "selected image channel"));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ d->hGradient = new ColorGradientWidget(ColorGradientWidget::Horizontal, 10, histoBox);
+ d->hGradient->setColors(TQColor("black"), TQColor("white"));
+
+ // -------------------------------------------------------------
+
+ TQHBoxLayout *hlay2 = new TQHBoxLayout(KDialog::spacingHint());
+ TQLabel *label3 = new TQLabel(i18n("Range:"), histogramPage);
+ label3->setAlignment(TQt::AlignLeft | TQt::AlignVCenter);
+ d->minInterv = new TQSpinBox(0, 255, 1, histogramPage);
+ d->minInterv->setValue(0);
+ TQWhatsThis::add(d->minInterv, i18n("<p>Select the minimal intensity "
+ "value of the histogram selection here."));
+ d->maxInterv = new TQSpinBox(0, 255, 1, histogramPage);
+ d->maxInterv->setValue(255);
+ TQWhatsThis::add(d->minInterv, i18n("<p>Select the maximal intensity value "
+ "of the histogram selection here."));
+ hlay2->addWidget(label3);
+ hlay2->addWidget(d->minInterv);
+ hlay2->addWidget(d->maxInterv);
+
+ // -------------------------------------------------------------
+
+ TQGroupBox *gbox = new TQGroupBox(2, TQt::Horizontal, i18n("Statistics"), histogramPage);
+ TQWhatsThis::add( gbox, i18n("<p>Here you can see the statistical results calculated from the "
+ "selected histogram part. These values are available for all "
+ "channels."));
+
+ TQLabel *label5 = new TQLabel(i18n("Pixels:"), gbox);
+ label5->setAlignment(TQt::AlignLeft | TQt::AlignVCenter);
+ d->labelPixelsValue = new TQLabel(gbox);
+ d->labelPixelsValue->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+
+ TQLabel *label7 = new TQLabel(i18n("Count:"), gbox);
+ label7->setAlignment(TQt::AlignLeft | TQt::AlignVCenter);
+ d->labelCountValue = new TQLabel(gbox);
+ d->labelCountValue->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+
+ TQLabel *label4 = new TQLabel(i18n("Mean:"), gbox);
+ label4->setAlignment(TQt::AlignLeft | TQt::AlignVCenter);
+ d->labelMeanValue = new TQLabel(gbox);
+ d->labelMeanValue->setAlignment (TQt::AlignRight | TQt::AlignVCenter);
+
+ TQLabel *label6 = new TQLabel(i18n("Std. deviation:"), gbox);
+ label6->setAlignment(TQt::AlignLeft | TQt::AlignVCenter);
+ d->labelStdDevValue = new TQLabel(gbox);
+ d->labelStdDevValue->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+
+ TQLabel *label8 = new TQLabel(i18n("Median:"), gbox);
+ label8->setAlignment(TQt::AlignLeft | TQt::AlignVCenter);
+ d->labelMedianValue = new TQLabel(gbox);
+ d->labelMedianValue->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+
+ TQLabel *label9 = new TQLabel(i18n("Percentile:"), gbox);
+ label9->setAlignment(TQt::AlignLeft | TQt::AlignVCenter);
+ d->labelPercentileValue = new TQLabel(gbox);
+ d->labelPercentileValue->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+
+ TQLabel *label11 = new TQLabel(i18n("Color depth:"), gbox);
+ label11->setAlignment(TQt::AlignLeft | TQt::AlignVCenter);
+ d->labelColorDepth = new TQLabel(gbox);
+ d->labelColorDepth->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+
+ TQLabel *label12 = new TQLabel(i18n("Alpha Channel:"), gbox);
+ label12->setAlignment(TQt::AlignLeft | TQt::AlignVCenter);
+ d->labelAlphaChannel = new TQLabel(gbox);
+ d->labelAlphaChannel->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+
+ topLayout->addMultiCellWidget(label1, 1, 1, 0, 0);
+ topLayout->addMultiCellWidget(d->channelCB, 1, 1, 1, 1);
+ topLayout->addMultiCellWidget(d->scaleBG, 1, 1, 3, 3);
+ topLayout->addMultiCellWidget(label10, 2, 2, 0, 0);
+ topLayout->addMultiCellWidget(d->colorsCB, 2, 2, 1, 1);
+ topLayout->addMultiCellWidget(d->regionBG, 2, 2, 3, 3);
+ topLayout->addMultiCellWidget(histoBox, 3, 4, 0, 3);
+ topLayout->addMultiCellLayout(hlay2, 5, 5, 0, 3);
+ topLayout->addMultiCellWidget(gbox, 6, 6, 0, 3);
+ topLayout->setColStretch(2, 10);
+ topLayout->setRowStretch(7, 10);
+
+ d->tab->insertTab(sv, i18n("Histogram"), ImagePropertiesColorsTabPriv::HISTOGRAM );
+
+ // ICC Profiles tab area ---------------------------------------
+
+ TQScrollView *sv2 = new TQScrollView(d->tab);
+ sv2->viewport()->setBackgroundMode(TQt::PaletteBackground);
+ sv2->setResizePolicy(TQScrollView::AutoOneFit);
+ sv2->setFrameStyle(TQFrame::NoFrame);
+
+ d->iccProfileWidget = new ICCProfileWidget(sv2->viewport());
+ sv2->addChild(d->iccProfileWidget);
+ d->tab->insertTab(sv2, i18n("ICC profile"), ImagePropertiesColorsTabPriv::ICCPROFILE);
+
+ // -------------------------------------------------------------
+
+ connect(d->channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(d->scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(d->colorsCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotColorsChanged(int)));
+
+ connect(d->regionBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotRenderingChanged(int)));
+
+ connect(d->histogramWidget, TQ_SIGNAL(signalIntervalChanged( int, int )),
+ this, TQ_SLOT(slotUpdateInterval(int, int)));
+
+ connect(d->histogramWidget, TQ_SIGNAL(signalMaximumValueChanged( int )),
+ this, TQ_SLOT(slotUpdateIntervRange(int)));
+
+ connect(d->histogramWidget, TQ_SIGNAL(signalHistogramComputationDone(bool)),
+ this, TQ_SLOT(slotRefreshOptions(bool)));
+
+ connect(d->histogramWidget, TQ_SIGNAL(signalHistogramComputationFailed(void)),
+ this, TQ_SLOT(slotHistogramComputationFailed(void)));
+
+ connect(d->minInterv, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotMinValueChanged(int)));
+
+ connect(d->maxInterv, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotMaxValueChanged(int)));
+
+ // -- read config ---------------------------------------------------------
+
+ TDEConfig* config = kapp->config();
+ config->setGroup("Image Properties SideBar");
+ d->tab->setCurrentPage(config->readNumEntry("ImagePropertiesColors Tab",
+ ImagePropertiesColorsTabPriv::HISTOGRAM));
+ d->iccProfileWidget->setMode(config->readNumEntry("ICC Level", ICCProfileWidget::SIMPLE));
+ d->iccProfileWidget->setCurrentItemByKey(config->readEntry("Current ICC Item", TQString()));
+
+ d->channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ d->scaleBG->setButton(config->readNumEntry("Histogram Scale", HistogramWidget::LogScaleHistogram));
+ d->colorsCB->setCurrentItem(config->readNumEntry("Histogram Color", 0)); // Red.
+ d->regionBG->setButton(config->readNumEntry("Histogram Rendering", HistogramWidget::FullImageHistogram));
+}
+
+ImagePropertiesColorsTab::~ImagePropertiesColorsTab()
+{
+ // If there is a currently histogram computation when dialog is closed,
+ // stop it before the d->image data are deleted automatically!
+ d->histogramWidget->stopHistogramComputation();
+
+ TDEConfig* config = kapp->config();
+ config->setGroup("Image Properties SideBar");
+ config->writeEntry("ImagePropertiesColors Tab", d->tab->currentPageIndex());
+ config->writeEntry("Histogram Channel", d->channelCB->currentItem());
+ config->writeEntry("Histogram Scale", d->scaleBG->selectedId());
+ config->writeEntry("Histogram Color", d->colorsCB->currentItem());
+ config->writeEntry("Histogram Rendering", d->regionBG->selectedId());
+ config->writeEntry("ICC Level", d->iccProfileWidget->getMode());
+ config->writeEntry("Current ICC Item", d->iccProfileWidget->getCurrentItemKey());
+ config->sync();
+
+ if (d->imageLoaderThread)
+ delete d->imageLoaderThread;
+
+ if (d->histogramWidget)
+ delete d->histogramWidget;
+
+ if (d->hGradient)
+ delete d->hGradient;
+
+ delete d;
+}
+
+void ImagePropertiesColorsTab::setData(const KURL& url, const TQRect &selectionArea,
+ DImg *img)
+{
+ // We might be getting duplicate events from AlbumIconView,
+ // which will cause all sorts of duplicate work.
+ // More importantly, while the loading thread can handle this pretty well,
+ // this will completely mess up the timing of progress info in the histogram widget.
+ // So filter here, before the stopHistogramComputation!
+ if (!img && url.path() == d->currentFilePath && d->inLoadingProcess)
+ return;
+
+ // This is necessary to stop computation because d->image.bits() is currently used by
+ // threaded histogram algorithm.
+ d->histogramWidget->stopHistogramComputation();
+
+ d->currentFilePath = TQString();
+ d->currentLoadingDescription = LoadingDescription();
+ d->iccProfileWidget->loadFromURL(KURL());
+
+ // Clear information.
+ d->labelMeanValue->clear();
+ d->labelPixelsValue->clear();
+ d->labelStdDevValue->clear();
+ d->labelCountValue->clear();
+ d->labelMedianValue->clear();
+ d->labelPercentileValue->clear();
+ d->labelColorDepth->clear();
+ d->labelAlphaChannel->clear();
+
+ if (url.isEmpty())
+ {
+ setEnabled(false);
+ return;
+ }
+
+ d->selectionArea = selectionArea;
+ d->image.reset();
+ setEnabled(true);
+
+ if (!img)
+ {
+ loadImageFromUrl(url);
+ }
+ else
+ {
+ d->image = img->copy();
+
+ if ( !d->image.isNull() )
+ {
+ getICCData();
+
+ // If a selection area is done in Image Editor and if the current image is the same
+ // in Image Editor, then compute too the histogram for this selection.
+ if (d->selectionArea.isValid())
+ {
+ d->imageSelection = d->image.copy(d->selectionArea);
+ d->histogramWidget->updateData(d->image.bits(), d->image.width(), d->image.height(),
+ d->image.sixteenBit(), d->imageSelection.bits(),
+ d->imageSelection.width(), d->imageSelection.height());
+ d->regionBG->show();
+ updateInformations();
+ }
+ else
+ {
+ d->histogramWidget->updateData(d->image.bits(), d->image.width(),
+ d->image.height(), d->image.sixteenBit());
+ d->regionBG->hide();
+ updateInformations();
+ }
+ }
+ else
+ {
+ d->histogramWidget->setLoadingFailed();
+ d->iccProfileWidget->setLoadingFailed();
+ slotHistogramComputationFailed();
+ }
+ }
+}
+
+void ImagePropertiesColorsTab::loadImageFromUrl(const KURL& url)
+{
+ // create thread on demand
+ if (!d->imageLoaderThread)
+ {
+ d->imageLoaderThread = new SharedLoadSaveThread();
+
+ connect(d->imageLoaderThread, TQ_SIGNAL(signalImageLoaded(const LoadingDescription &, const DImg&)),
+ this, TQ_SLOT(slotLoadImageFromUrlComplete(const LoadingDescription &, const DImg&)));
+
+ connect(d->imageLoaderThread, TQ_SIGNAL(signalMoreCompleteLoadingAvailable(const LoadingDescription &, const LoadingDescription &)),
+ this, TQ_SLOT(slotMoreCompleteLoadingAvailable(const LoadingDescription &, const LoadingDescription &)));
+ }
+
+ LoadingDescription desc = LoadingDescription(url.path());
+
+ if (DImg::fileFormat(desc.filePath) == DImg::RAW)
+ {
+ // use raw settings optimized for speed
+
+ DRawDecoding rawDecodingSettings = DRawDecoding();
+ rawDecodingSettings.optimizeTimeLoading();
+ desc = LoadingDescription(desc.filePath, rawDecodingSettings);
+ }
+
+ if (d->currentLoadingDescription.equalsOrBetterThan(desc))
+ return;
+
+ d->currentFilePath = desc.filePath;
+ d->currentLoadingDescription = desc;
+ d->inLoadingProcess = true;
+
+ d->imageLoaderThread->load(d->currentLoadingDescription,
+ SharedLoadSaveThread::AccessModeRead,
+ SharedLoadSaveThread::LoadingPolicyFirstRemovePrevious);
+
+ d->histogramWidget->setDataLoading();
+ d->iccProfileWidget->setDataLoading();
+}
+
+void ImagePropertiesColorsTab::slotLoadImageFromUrlComplete(const LoadingDescription &loadingDescription, const DImg& img)
+{
+ // Discard any leftover messages from previous, possibly aborted loads
+ if ( !loadingDescription.equalsOrBetterThan(d->currentLoadingDescription) )
+ return;
+
+ if ( !img.isNull() )
+ {
+ d->histogramWidget->updateData(img.bits(), img.width(), img.height(), img.sixteenBit());
+
+ // As a safety precaution, this must be changed only after updateData is called,
+ // which stops computation because d->image.bits() is currently used by threaded histogram algorithm.
+ d->image = img;
+ d->regionBG->hide();
+ updateInformations();
+ getICCData();
+ }
+ else
+ {
+ d->histogramWidget->setLoadingFailed();
+ d->iccProfileWidget->setLoadingFailed();
+ slotHistogramComputationFailed();
+ }
+ d->inLoadingProcess = false;
+}
+
+void ImagePropertiesColorsTab::slotMoreCompleteLoadingAvailable(const LoadingDescription &oldLoadingDescription,
+ const LoadingDescription &newLoadingDescription)
+{
+ if (oldLoadingDescription == d->currentLoadingDescription &&
+ newLoadingDescription.equalsOrBetterThan(d->currentLoadingDescription))
+ {
+ // Yes, we do want to stop our old time-optimized loading and chain to the current, more complete loading.
+ // Even the time-optimized raw loading takes significant time, and we must avoid two dcraw instances running
+ // at a time.
+ d->currentLoadingDescription = newLoadingDescription;
+ d->inLoadingProcess = true;
+ d->imageLoaderThread->load(newLoadingDescription,
+ SharedLoadSaveThread::AccessModeRead,
+ SharedLoadSaveThread::LoadingPolicyFirstRemovePrevious);
+ }
+}
+
+void ImagePropertiesColorsTab::setSelection(const TQRect &selectionArea)
+{
+ // This is necessary to stop computation because d->image.bits() is currently used by
+ // threaded histogram algorithm.
+
+ d->histogramWidget->stopHistogramComputation();
+ d->selectionArea = selectionArea;
+
+ if (d->selectionArea.isValid())
+ {
+ d->imageSelection = d->image.copy(d->selectionArea);
+ d->histogramWidget->updateSelectionData(d->imageSelection.bits(), d->imageSelection.width(),
+ d->imageSelection.height(), d->imageSelection.sixteenBit());
+ d->regionBG->show();
+ }
+ else
+ {
+ d->regionBG->hide();
+ slotRenderingChanged(HistogramWidget::FullImageHistogram);
+ }
+}
+
+void ImagePropertiesColorsTab::slotRefreshOptions(bool /*sixteenBit*/)
+{
+ slotChannelChanged(d->channelCB->currentItem());
+ slotScaleChanged(d->scaleBG->selectedId());
+ slotColorsChanged(d->colorsCB->currentItem());
+
+ if (d->selectionArea.isValid())
+ slotRenderingChanged(d->regionBG->selectedId());
+}
+
+void ImagePropertiesColorsTab::slotHistogramComputationFailed()
+{
+ d->imageSelection.reset();
+ d->image.reset();
+}
+
+void ImagePropertiesColorsTab::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case RedChannel:
+ d->histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ d->hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ d->colorsCB->setEnabled(false);
+ break;
+
+ case GreenChannel:
+ d->histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ d->hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ d->colorsCB->setEnabled(false);
+ break;
+
+ case BlueChannel:
+ d->histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ d->hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ d->colorsCB->setEnabled(false);
+ break;
+
+ case AlphaChannel:
+ d->histogramWidget->m_channelType = HistogramWidget::AlphaChannelHistogram;
+ d->hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ d->colorsCB->setEnabled(false);
+ break;
+
+ case ColorChannels:
+ d->histogramWidget->m_channelType = HistogramWidget::ColorChannelsHistogram;
+ d->hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ d->colorsCB->setEnabled(true);
+ break;
+
+ default: // Luminosity.
+ d->histogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ d->hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ d->colorsCB->setEnabled(false);
+ break;
+ }
+
+ d->histogramWidget->repaint(false);
+ updateStatistiques();
+}
+
+void ImagePropertiesColorsTab::slotScaleChanged(int scale)
+{
+ d->histogramWidget->m_scaleType = scale;
+ d->histogramWidget->repaint(false);
+}
+
+void ImagePropertiesColorsTab::slotColorsChanged(int color)
+{
+ switch(color)
+ {
+ case AllColorsGreen:
+ d->histogramWidget->m_colorType = HistogramWidget::GreenColor;
+ break;
+
+ case AllColorsBlue:
+ d->histogramWidget->m_colorType = HistogramWidget::BlueColor;
+ break;
+
+ default: // Red.
+ d->histogramWidget->m_colorType = HistogramWidget::RedColor;
+ break;
+ }
+
+ d->histogramWidget->repaint(false);
+ updateStatistiques();
+}
+
+void ImagePropertiesColorsTab::slotRenderingChanged(int rendering)
+{
+ d->histogramWidget->m_renderingType = rendering;
+ d->histogramWidget->repaint(false);
+ updateStatistiques();
+}
+
+void ImagePropertiesColorsTab::slotMinValueChanged(int min)
+{
+ // Called when user changes values of spin box.
+ // Communicate the change to histogram widget.
+
+ // make the one control "push" the other
+ if (min == d->maxInterv->value()+1)
+ d->maxInterv->setValue(min);
+ d->maxInterv->setMinValue(min-1);
+ d->histogramWidget->slotMinValueChanged(min);
+ updateStatistiques();
+}
+
+void ImagePropertiesColorsTab::slotMaxValueChanged(int max)
+{
+ if (max == d->minInterv->value()-1)
+ d->minInterv->setValue(max);
+ d->minInterv->setMaxValue(max+1);
+ d->histogramWidget->slotMaxValueChanged(max);
+ updateStatistiques();
+}
+
+void ImagePropertiesColorsTab::slotUpdateInterval(int min, int max)
+{
+ // Called when value is set from within histogram widget.
+ // Block signals to prevent slotMinValueChanged and
+ // slotMaxValueChanged being called.
+ d->minInterv->blockSignals(true);
+ d->minInterv->setMaxValue(max+1);
+ d->minInterv->setValue(min);
+ d->minInterv->blockSignals(false);
+
+ d->maxInterv->blockSignals(true);
+ d->maxInterv->setMinValue(min-1);
+ d->maxInterv->setValue(max);
+ d->maxInterv->blockSignals(false);
+
+ updateStatistiques();
+}
+
+void ImagePropertiesColorsTab::slotUpdateIntervRange(int range)
+{
+ d->maxInterv->setMaxValue( range );
+}
+
+void ImagePropertiesColorsTab::updateInformations()
+{
+ d->labelColorDepth->setText(d->image.sixteenBit() ? i18n("16 bits") : i18n("8 bits"));
+ d->labelAlphaChannel->setText(d->image.hasAlpha() ? i18n("Yes") : i18n("No"));
+}
+
+void ImagePropertiesColorsTab::updateStatistiques()
+{
+ TQString value;
+ int min = d->minInterv->value();
+ int max = d->maxInterv->value();
+ int channel = d->channelCB->currentItem();
+
+ if ( channel == HistogramWidget::ColorChannelsHistogram )
+ channel = d->colorsCB->currentItem()+1;
+
+ double mean = d->histogramWidget->m_imageHistogram->getMean(channel, min, max);
+ d->labelMeanValue->setText(value.setNum(mean, 'f', 1));
+
+ double pixels = d->histogramWidget->m_imageHistogram->getPixels();
+ d->labelPixelsValue->setText(value.setNum((float)pixels, 'f', 0));
+
+ double stddev = d->histogramWidget->m_imageHistogram->getStdDev(channel, min, max);
+ d->labelStdDevValue->setText(value.setNum(stddev, 'f', 1));
+
+ double counts = d->histogramWidget->m_imageHistogram->getCount(channel, min, max);
+ d->labelCountValue->setText(value.setNum((float)counts, 'f', 0));
+
+ double median = d->histogramWidget->m_imageHistogram->getMedian(channel, min, max);
+ d->labelMedianValue->setText(value.setNum(median, 'f', 1));
+
+ double percentile = (pixels > 0 ? (100.0 * counts / pixels) : 0.0);
+ d->labelPercentileValue->setText(value.setNum(percentile, 'f', 1));
+}
+
+void ImagePropertiesColorsTab::getICCData()
+{
+ if (d->image.getICCProfil().isNull())
+ {
+ d->iccProfileWidget->setLoadingFailed();
+ }
+ else
+ {
+ d->embedded_profile = d->image.getICCProfil();
+ d->iccProfileWidget->loadFromData(d->currentFilePath, d->embedded_profile);
+ }
+}
+
+} // NameSpace Digikam
+