diff options
Diffstat (limited to 'src/libs/imageproperties/imagepropertiescolorstab.cpp')
-rw-r--r-- | src/libs/imageproperties/imagepropertiescolorstab.cpp | 799 |
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 + |