/* ============================================================ * * 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 <klocale.h> #include <ksqueezedtextlabel.h> #include <kapplication.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, Qt::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, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotChannelChanged(int))); connect(d->scaleBG, TQT_SIGNAL(released(int)), this, TQT_SLOT(slotScaleChanged(int))); connect(d->colorsCB, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotColorsChanged(int))); connect(d->regionBG, TQT_SIGNAL(released(int)), this, TQT_SLOT(slotRenderingChanged(int))); connect(d->histogramWidget, TQT_SIGNAL(signalIntervalChanged( int, int )), this, TQT_SLOT(slotUpdateInterval(int, int))); connect(d->histogramWidget, TQT_SIGNAL(signalMaximumValueChanged( int )), this, TQT_SLOT(slotUpdateIntervRange(int))); connect(d->histogramWidget, TQT_SIGNAL(signalHistogramComputationDone(bool)), this, TQT_SLOT(slotRefreshOptions(bool))); connect(d->histogramWidget, TQT_SIGNAL(signalHistogramComputationFailed(void)), this, TQT_SLOT(slotHistogramComputationFailed(void))); connect(d->minInterv, TQT_SIGNAL(valueChanged (int)), this, TQT_SLOT(slotMinValueChanged(int))); connect(d->maxInterv, TQT_SIGNAL(valueChanged (int)), this, TQT_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, TQT_SIGNAL(signalImageLoaded(const LoadingDescription &, const DImg&)), this, TQT_SLOT(slotLoadImageFromUrlComplete(const LoadingDescription &, const DImg&))); connect(d->imageLoaderThread, TQT_SIGNAL(signalMoreCompleteLoadingAvailable(const LoadingDescription &, const LoadingDescription &)), this, TQT_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