krita
kis_histogram_view.cc00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <math.h>
00020
00021 #include <qpainter.h>
00022 #include <qpixmap.h>
00023 #include <qlabel.h>
00024 #include <qcombobox.h>
00025 #include <qbuttongroup.h>
00026 #include <qpushbutton.h>
00027 #include <qscrollbar.h>
00028
00029 #include <kdebug.h>
00030
00031 #include "kis_channelinfo.h"
00032 #include "kis_histogram.h"
00033 #include "kis_global.h"
00034 #include "kis_types.h"
00035 #include "kis_layer.h"
00036 #include "kis_colorspace.h"
00037 #include "kis_histogram_view.h"
00038 #include "kis_basic_histogram_producers.h"
00039 #include "kis_paint_device.h"
00040
00041 KisHistogramView::KisHistogramView(QWidget *parent, const char *name, WFlags f)
00042 : QLabel(parent, name, f)
00043 {
00044
00045
00046 setScaledContents(true);
00047 setFrameShape(QFrame::Box);
00048 }
00049
00050 KisHistogramView::~KisHistogramView()
00051 {
00052 }
00053
00054 void KisHistogramView::setPaintDevice(KisPaintDeviceSP dev)
00055 {
00056 m_cs = dev->colorSpace();
00057
00058 setChannels();
00059
00060 if (!m_currentProducer)
00061 return;
00062
00063 m_from = m_currentProducer->viewFrom();
00064 m_width = m_currentProducer->viewWidth();
00065
00066 m_histogram = new KisHistogram(dev, m_currentProducer, LINEAR);
00067
00068 updateHistogram();
00069 }
00070
00071 void KisHistogramView::setHistogram(KisHistogramSP histogram)
00072 {
00073 m_cs = 0;
00074 m_histogram = histogram;
00075 m_currentProducer = m_histogram->producer();
00076 m_from = m_currentProducer->viewFrom();
00077 m_width = m_currentProducer->viewWidth();
00078
00079 m_comboInfo.clear();
00080 m_channelStrings.clear();
00081 m_channels.clear();
00082 m_channelToOffset.clear();
00083
00084 addProducerChannels(m_currentProducer);
00085
00086
00087 m_color = false;
00088 m_channels.append(m_comboInfo.at(1).channel);
00089 m_channelToOffset.append(0);
00090
00091 updateHistogram();
00092 }
00093
00094 void KisHistogramView::setView(double from, double size)
00095 {
00096 m_from = from;
00097 m_width = size;
00098 if (m_from + m_width > 1.0)
00099 m_from = 1.0 - m_width;
00100 m_histogram->producer()->setView(m_from, m_width);
00101
00102 m_histogram->updateHistogram();
00103 updateHistogram();
00104 }
00105
00106 KisHistogramProducerSP KisHistogramView::currentProducer()
00107 {
00108 return m_currentProducer;
00109 }
00110
00111 QStringList KisHistogramView::channelStrings()
00112 {
00113 return m_channelStrings;
00114 }
00115
00116 KisIDList KisHistogramView::listProducers()
00117 {
00118 if (m_cs)
00119 return KisHistogramProducerFactoryRegistry::instance()->listKeysCompatibleWith(m_cs);
00120 return KisIDList();
00121 }
00122
00123 void KisHistogramView::setCurrentChannels(const KisID& producerID, QValueVector<KisChannelInfo *> channels)
00124 {
00125 setCurrentChannels(
00126 KisHistogramProducerFactoryRegistry::instance()->get(producerID)->generate(),
00127 channels);
00128 }
00129
00130 void KisHistogramView::setCurrentChannels(KisHistogramProducerSP producer, QValueVector<KisChannelInfo *> channels)
00131 {
00132 m_currentProducer = producer;
00133 m_currentProducer->setView(m_from, m_width);
00134 m_histogram->setProducer(m_currentProducer);
00135 m_histogram->updateHistogram();
00136 m_histogram->setChannel(0);
00137
00138 m_channels.clear();
00139 m_channelToOffset.clear();
00140
00141 if (channels.count() == 0) {
00142 updateHistogram();
00143 return;
00144 }
00145
00146 QValueVector<KisChannelInfo *> producerChannels = m_currentProducer->channels();
00147
00148 for (uint i = 0; i < channels.count(); i++) {
00149
00150 for (uint j = 0; j < producerChannels.count(); j++) {
00151 if (channels.at(i)->name() == producerChannels.at(j)->name()) {
00152 m_channelToOffset.append(m_channels.count());
00153 m_channels.append(channels.at(i));
00154 }
00155 }
00156 }
00157
00158 updateHistogram();
00159 }
00160
00161 bool KisHistogramView::hasColor()
00162 {
00163 return m_color;
00164 }
00165
00166 void KisHistogramView::setColor(bool set)
00167 {
00168 if (set != m_color) {
00169 m_color = set;
00170 updateHistogram();
00171 }
00172 }
00173
00174 void KisHistogramView::setActiveChannel(int channel)
00175 {
00176 ComboboxInfo info = m_comboInfo.at(channel);
00177 if (info.producer.data() != m_currentProducer.data()) {
00178 m_currentProducer = info.producer;
00179 m_currentProducer->setView(m_from, m_width);
00180 m_histogram->setProducer(m_currentProducer);
00181 m_histogram->updateHistogram();
00182 }
00183
00184 m_channels.clear();
00185 m_channelToOffset.clear();
00186
00187 if (!m_currentProducer) {
00188 updateHistogram();
00189 return;
00190 }
00191
00192 if (info.isProducer) {
00193 m_color = true;
00194 m_channels = m_currentProducer->channels();
00195 for (uint i = 0; i < m_channels.count(); i++)
00196 m_channelToOffset.append(i);
00197 m_histogram->setChannel(0);
00198 } else {
00199 m_color = false;
00200 QValueVector<KisChannelInfo *> channels = m_currentProducer->channels();
00201 for (uint i = 0; i < channels.count(); i++) {
00202 KisChannelInfo* channel = channels.at(i);
00203 if (channel->name() == info.channel->name()) {
00204 m_channels.append(channel);
00205 m_channelToOffset.append(i);
00206 break;
00207 }
00208 }
00209 }
00210
00211 updateHistogram();
00212 }
00213
00214 void KisHistogramView::setHistogramType(enumHistogramType type)
00215 {
00216 m_histogram->setHistogramType(type);
00217 updateHistogram();
00218 }
00219
00220 void KisHistogramView::setChannels()
00221 {
00222 m_comboInfo.clear();
00223 m_channelStrings.clear();
00224 m_channels.clear();
00225 m_channelToOffset.clear();
00226
00227 KisIDList list = KisHistogramProducerFactoryRegistry::instance()->listKeysCompatibleWith(m_cs);
00228
00229 if (list.count() == 0) {
00230
00231 KisGenericRGBHistogramProducerFactory f;
00232 addProducerChannels(f.generate());
00233 } else {
00234 for (uint i = 0; i < list.count(); i++) {
00235 KisID id(*(list.at(i)));
00236 addProducerChannels( KisHistogramProducerFactoryRegistry::instance()->get(id)->generate() );
00237 }
00238 }
00239
00240 m_currentProducer = m_comboInfo.at(0).producer;
00241 m_color = false;
00242
00243 m_channels.append(m_comboInfo.at(1).channel);
00244 m_channelToOffset.append(0);
00245 }
00246
00247 void KisHistogramView::addProducerChannels(KisHistogramProducerSP producer) {
00248 ComboboxInfo info;
00249 info.isProducer = true;
00250 info.producer = producer;
00251
00252 QValueVector<KisChannelInfo *> channels = info.producer->channels();
00253 int count = channels.count();
00254 m_comboInfo.append(info);
00255 m_channelStrings.append(producer->id() . name());
00256 for (int j = 0; j < count; j++) {
00257 info.isProducer = false;
00258 info.channel = channels.at(j);
00259 m_comboInfo.append(info);
00260 m_channelStrings.append(QString(" ").append(info.channel->name()));
00261 }
00262 }
00263
00264 void KisHistogramView::updateHistogram()
00265 {
00266 Q_UINT32 height = this->height();
00267 int selFrom, selTo;
00268
00269 if (!m_currentProducer) {
00270 return;
00271 }
00272
00273 Q_INT32 bins = m_histogram->producer()->numberOfBins();
00274 m_pix = QPixmap(bins, height);
00275 m_pix.fill();
00276 QPainter p(&m_pix);
00277 p.setBrush(Qt::black);
00278
00279
00280 if (m_histogram->hasSelection()) {
00281 double width = m_histogram->selectionTo() - m_histogram->selectionFrom();
00282 double factor = static_cast<double>(bins) / m_histogram->producer()->viewWidth();
00283 selFrom = static_cast<int>(m_histogram->selectionFrom() * factor);
00284 selTo = selFrom + static_cast<int>(width * factor);
00285 p.drawRect(selFrom, 0, selTo - selFrom, height);
00286 } else {
00287
00288 selFrom = -1;
00289 selTo = 2;
00290 }
00291
00292 Q_INT32 i = 0;
00293 double highest = 0;
00294 bool blackOnBlack = false;
00295
00296
00297
00298 for (uint chan = 0; chan < m_channels.count(); chan++) {
00299 m_histogram->setChannel(m_channelToOffset.at(chan));
00300 if ((double)m_histogram->calculations().getHighest() > highest)
00301 highest = (double)m_histogram->calculations().getHighest();
00302 }
00303
00304 for (uint chan = 0; chan < m_channels.count(); chan++) {
00305 QColor color;
00306 m_histogram->setChannel(m_channelToOffset.at(chan));
00307
00308 if (m_color) {
00309 color = m_channels.at(chan)->color();
00310 p.setPen(color);
00311 } else {
00312 color = Qt::black;
00313 }
00314 blackOnBlack = (color == Qt::black);
00315
00316 if (m_histogram->getHistogramType() == LINEAR) {
00317 double factor = (double)height / highest;
00318 for( i=0; i<bins; ++i ) {
00319
00320
00321 if (i >= selFrom && i < selTo && blackOnBlack) {
00322 p.setPen(Qt::white);
00323 } else {
00324 p.setPen(color);
00325 }
00326 p.drawLine(i, height, i, height - int(m_histogram->getValue(i) * factor));
00327 }
00328 } else {
00329 double factor = (double)height / (double)log(highest);
00330 for( i = 0; i < bins; ++i ) {
00331
00332 if (i >= selFrom && i < selTo && blackOnBlack) {
00333 p.setPen(Qt::white);
00334 } else {
00335 p.setPen(color);
00336 }
00337 p.drawLine(i, height, i,
00338 height - int(log((double)m_histogram->getValue(i)) * factor));
00339 }
00340 }
00341 }
00342
00343 setPixmap(m_pix);
00344 }
00345
00346 void KisHistogramView::mousePressEvent(QMouseEvent * e) {
00347 if (e->button() == Qt::RightButton)
00348 emit rightClicked(e->globalPos());
00349 else
00350 QLabel::mousePressEvent(e);
00351 }
00352
00353
00354 #include "kis_histogram_view.moc"
|