00001 #include "gradients.h"
00002 #include "hoverpoints.h"
00003
00004 #include <QtOpenGL>
00005
00006 #include <GL/gl.h>
00007 #include <GL/glu.h>
00008 #include <GL/glut.h>
00009
00010 #include <iostream>
00011 #include <math.h>
00012
00013 ShadeWidget::ShadeWidget(ShadeType type, QWidget *parent)
00014 : QWidget(parent), m_shade_type(type), m_alpha_gradient(QLinearGradient(0, 0, 0, 0))
00015 {
00016
00017
00018 if (m_shade_type == ARGBShade) {
00019 QPixmap pm(20, 20);
00020 QPainter pmp(&pm);
00021 pmp.fillRect(0, 0, 10, 10, Qt::lightGray);
00022 pmp.fillRect(10, 10, 10, 10, Qt::lightGray);
00023 pmp.fillRect(0, 10, 10, 10, Qt::darkGray);
00024 pmp.fillRect(10, 0, 10, 10, Qt::darkGray);
00025 pmp.end();
00026 QPalette pal = palette();
00027 pal.setBrush(backgroundRole(), QBrush(pm));
00028 setAutoFillBackground(true);
00029 setPalette(pal);
00030
00031 } else {
00032 setAttribute(Qt::WA_NoBackground);
00033
00034 }
00035
00036 QPolygonF points;
00037 points << QPointF(0, sizeHint().height())
00038 << QPointF(sizeHint().width(), 0);
00039
00040 m_hoverPoints = new HoverPoints(this, HoverPoints::CircleShape);
00041
00042 m_hoverPoints->setPoints(points);
00043 m_hoverPoints->setPointLock(0, HoverPoints::LockToLeft);
00044 m_hoverPoints->setPointLock(1, HoverPoints::LockToRight);
00045 m_hoverPoints->setSortType(HoverPoints::XSort);
00046
00047
00048 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
00049
00050 connect(m_hoverPoints, SIGNAL(pointsChanged(const QPolygonF &)), this, SIGNAL(colorsChanged()));
00051
00052 m_histogram.clear();
00053 m_norm_histogram.clear();
00054 m_norm_exp_histogram.clear();
00055 max_histogram_bin = 0;
00056 }
00057
00058
00059 QPolygonF ShadeWidget::points() const
00060 {
00061 return m_hoverPoints->points();
00062 }
00063
00064
00065 uint ShadeWidget::colorAt(int x)
00066 {
00067 generateShade();
00068
00069 QPolygonF pts = m_hoverPoints->points();
00070 for (int i=1; i < pts.size(); ++i) {
00071 qreal candidate_left_x = pts.at(i-1).x();
00072 qreal candidate_left_y = pts.at(i-1).y();
00073 qreal candidate_right_x = pts.at(i).x();
00074 qreal candidate_right_y = pts.at(i).y();
00075 qreal lx1,lx2,ly1,ly2,ll;
00076 if ( candidate_left_x<= x && candidate_right_x >= x) {
00077 QLineF l(pts.at(i-1), pts.at(i));
00078
00079 ll = l.length();
00080
00081 l.setLength(l.length() * ((x - l.x1()) / l.dx()));
00082
00083 ll = l.length();
00084 lx1 = l.x1();
00085 lx2 = l.x2();
00086 ly1 = l.y1();
00087 ly2 = l.y2();
00088
00089 int widget_width = m_shade.width();
00090 int widget_height = m_shade.height();
00091
00092 qreal min_px = qMin(l.x2(), qreal(m_shade.width() - 1));
00093 qreal min_py = qMin(l.y2(), qreal(m_shade.height() - 1));
00094
00095 int px = qRound(min_px);
00096 int py = qRound(min_py);
00097
00098 QRgb p1 = m_shade.pixel(px,py);
00099 int pred = qRed(p1);
00100 int pgreen = qGreen(p1);
00101 int pblue = qBlue(p1);
00102 int palpha = qAlpha(p1);
00103
00104 return p1;
00105 }
00106 }
00107 return 0;
00108 }
00109
00110
00111 void ShadeWidget::setGradientStops(const QGradientStops &stops)
00112 {
00113 if (m_shade_type == ARGBShade) {
00114 m_alpha_gradient = QLinearGradient(0, 0, width()-1, 0);
00115
00116 for (int i=0; i<stops.size(); ++i) {
00117 QColor c = stops.at(i).second;
00118 m_alpha_gradient.setColorAt(stops.at(i).first, QColor(c.red(), c.green(), c.blue()));
00119 }
00120
00121 m_shade = QImage();
00122 generateShade();
00123 update();
00124 }
00125 }
00126
00127 void ShadeWidget::setHistogram(QList<int> &histogram)
00128 {
00129 m_histogram = histogram;
00130
00131 unsigned int scalars_count;
00132
00133 scalars_count = 0;
00134
00135
00136 max_histogram_bin = 0;
00137 for (int i = 0; i < m_histogram.size(); i++)
00138 {
00139
00140
00141 scalars_count += m_histogram.at(i);
00142
00143 if (m_histogram.at(i) > max_histogram_bin)
00144 if(i!=0)
00145 max_histogram_bin = m_histogram.at(i);
00146 }
00147
00148
00149
00150 m_norm_histogram.clear();
00151 for (int i = 0; i < m_histogram.size(); i++)
00152 {
00153 if (m_histogram.at(i) != 0)
00154 m_norm_histogram.append((float)((float)m_histogram.at(i)/(float)max_histogram_bin));
00155 else
00156 m_norm_histogram.append(0);
00157
00158
00159 }
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 generateShade();
00195 update();
00196 }
00197
00198 void ShadeWidget::drawHistogram()
00199 {
00200
00201
00202
00203
00204
00205
00206
00207
00208 int widget_height = this->height();
00209
00210 QPainter p(this);
00211
00212
00213 float lx1,lx2,ly1,ly2;
00214
00215 QColor histogram_color = QColor(255,255,255,128);
00216
00217 for (int i = 0; i < m_norm_histogram.size(); i++)
00218 {
00219
00220 lx1 = (float)i;
00221 ly1 = (float)widget_height;
00222 lx2 = (float)i;
00223 ly2 = (float)((float)widget_height - m_norm_histogram.at(i)*((float)widget_height));
00224
00225
00226 QLineF line(lx1, ly1, lx2, ly2);
00227 p.setPen(histogram_color);
00228 p.drawLine(line);
00229 }
00230 }
00231
00232 void ShadeWidget::paintEvent(QPaintEvent *)
00233 {
00234 drawHistogram();
00235
00236 generateShade();
00237
00238 QPainter p(this);
00239 p.drawImage(0, 0, m_shade);
00240
00241 if (m_shade_type != ARGBShade) {
00242 drawHistogram();
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 }
00254
00255
00256 void ShadeWidget::generateShade()
00257 {
00258 if (m_shade.isNull() || m_shade.size() != size()) {
00259
00260 if (m_shade_type == ARGBShade) {
00261 m_shade = QImage(size(), QImage::Format_ARGB32_Premultiplied);
00262 m_shade.fill(0);
00263
00264 QPainter p(&m_shade);
00265 p.fillRect(rect(), m_alpha_gradient);
00266
00267 p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
00268
00269 QLinearGradient fade(0, 0, 0, height()-1);
00270 fade.setColorAt(0, QColor(0, 0, 0, 255));
00271 fade.setColorAt(1, QColor(0, 0, 0, 0));
00272 p.fillRect(rect(), fade);
00273
00274
00275 } else {
00276 m_shade = QImage(size(), QImage::Format_RGB32);
00277 QLinearGradient shade(0, 0, 0, height()-1);
00278 shade.setColorAt(1, Qt::black);
00279
00280 if (m_shade_type == RedShade)
00281 shade.setColorAt(0, Qt::red);
00282 else if (m_shade_type == GreenShade)
00283 shade.setColorAt(0, Qt::green);
00284 else
00285 shade.setColorAt(0, Qt::blue);
00286
00287 QPainter p(&m_shade);
00288 p.fillRect(rect(), shade);
00289 }
00290 }
00291
00292
00293 }
00294
00295
00296 GradientEditor::GradientEditor(QWidget *parent)
00297 : QWidget(parent)
00298 {
00299 QVBoxLayout *vbox = new QVBoxLayout(this);
00300 vbox->setSpacing(1);
00301 vbox->setMargin(1);
00302
00303 m_red_shade = new ShadeWidget(ShadeWidget::RedShade, this);
00304 m_green_shade = new ShadeWidget(ShadeWidget::GreenShade, this);
00305 m_blue_shade = new ShadeWidget(ShadeWidget::BlueShade, this);
00306 m_alpha_shade = new ShadeWidget(ShadeWidget::ARGBShade, this);
00307
00308 vbox->addWidget(m_red_shade);
00309 vbox->addWidget(m_green_shade);
00310 vbox->addWidget(m_blue_shade);
00311 vbox->addWidget(m_alpha_shade);
00312
00313 connect(m_red_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated()));
00314 connect(m_green_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated()));
00315 connect(m_blue_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated()));
00316 connect(m_alpha_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated()));
00317 }
00318
00319
00320 inline static bool x_less_than(const QPointF &p1, const QPointF &p2)
00321 {
00322 return p1.x() < p2.x();
00323 }
00324
00325
00326 void GradientEditor::pointsUpdated()
00327 {
00328 double w = m_alpha_shade->width();
00329
00330 QGradientStops stops;
00331
00332 QPolygonF points;
00333
00334 points += m_red_shade->points();
00335 points += m_green_shade->points();
00336 points += m_blue_shade->points();
00337 points += m_alpha_shade->points();
00338
00339 qSort(points.begin(), points.end(), x_less_than);
00340
00341 for (int i=0; i<points.size(); ++i) {
00342 double x = int(points.at(i).x());
00343 if (i < points.size() - 1 && x == points.at(i+1).x())
00344 continue;
00345 QColor color((0x00ff0000 & m_red_shade->colorAt(int(x))) >> 16,
00346 (0x0000ff00 & m_green_shade->colorAt(int(x))) >> 8,
00347 (0x000000ff & m_blue_shade->colorAt(int(x))),
00348 (0xff000000 & m_alpha_shade->colorAt(int(x))) >> 24);
00349
00350
00351 int r1 = (0x00ff0000 & m_red_shade->colorAt(int(x))) >> 16;
00352 int g1 = (0x0000ff00 & m_green_shade->colorAt(int(x))) >> 8;
00353 int b1 = (0x000000ff & m_blue_shade->colorAt(int(x)));
00354 int a1 = (0xff000000 & m_alpha_shade->colorAt(int(x)) >> 24);
00355
00356 if (x / w > 1)
00357 return;
00358
00359 stops << QGradientStop(x / w, color);
00360 }
00361
00362 m_alpha_shade->setGradientStops(stops);
00363
00364 emit gradientStopsChanged(stops);
00365 }
00366
00367 void GradientEditor::setHistogram(QList<int> &histogram_list)
00368 {
00369 m_histogram = histogram_list;
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 m_red_shade->setHistogram(m_histogram);
00380 m_green_shade->setHistogram(m_histogram);
00381 m_blue_shade->setHistogram(m_histogram);
00382 m_alpha_shade->setHistogram(m_histogram);
00383
00384
00385 }
00386
00387 static void set_shade_points(const QPolygonF &points, ShadeWidget *shade)
00388 {
00389 shade->hoverPoints()->setPoints(points);
00390 shade->hoverPoints()->setPointLock(0, HoverPoints::LockToLeft);
00391 shade->hoverPoints()->setPointLock(points.size() - 1, HoverPoints::LockToRight);
00392 shade->update();
00393 }
00394
00395 void GradientEditor::setGradientStops(const QGradientStops &stops)
00396 {
00397 QPolygonF pts_red, pts_green, pts_blue, pts_alpha;
00398
00399 double h_red = m_red_shade->height();
00400 double h_green = m_green_shade->height();
00401 double h_blue = m_blue_shade->height();
00402 double h_alpha = m_alpha_shade->height();
00403
00404 double w_red = m_red_shade->width();
00405 double w_green = m_green_shade->width();
00406 double w_blue = m_blue_shade->width();
00407 double w_alpha = m_alpha_shade->width();
00408
00409
00410 for (int i=0; i<stops.size(); ++i) {
00411 double pos = stops.at(i).first;
00412 QRgb color = stops.at(i).second.rgba();
00413
00414 qreal red_x = pos * w_red;
00415 qreal red_y = h_red - qRed(color) * h_red / 255;
00416
00417 qreal green_x = pos * w_green;
00418 qreal green_y = h_green - qGreen(color) * h_green / 255;
00419
00420 qreal blue_x = pos * w_blue;
00421 qreal blue_y = h_blue - qBlue(color) * h_blue / 255;
00422
00423 qreal alpha_x = pos * w_alpha;
00424 qreal alpha_y = h_alpha - qAlpha(color) * h_alpha / 255;
00425
00426 pts_red << QPointF(red_x, red_y);
00427 pts_green << QPointF(green_x, green_y);
00428 pts_blue << QPointF(blue_x, blue_y);
00429 pts_alpha << QPointF(alpha_x, alpha_y);
00430 }
00431
00432 set_shade_points(pts_red, m_red_shade);
00433 set_shade_points(pts_green, m_green_shade);
00434 set_shade_points(pts_blue, m_blue_shade);
00435 set_shade_points(pts_alpha, m_alpha_shade);
00436
00437 emit gradientStopsChanged(stops);
00438
00439 }
00440
00441 GradientWidget::GradientWidget(QWidget *parent)
00442 : QWidget(parent)
00443 {
00444 QGroupBox *mainGroup = new QGroupBox(this);
00445 mainGroup->setTitle("Color editor");
00446
00447 QVBoxLayout *mainLayout = new QVBoxLayout(mainGroup);
00448
00449 m_editor = new GradientEditor(mainGroup);
00450 mainLayout->addWidget(m_editor);
00451
00452 tf_widget = new tfGLWidget(mainGroup);
00453 mainLayout->addWidget(tf_widget);
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 connect(m_editor, SIGNAL(gradientStopsChanged(const QGradientStops &)), this, SLOT(rendertf(const QGradientStops &)));
00487
00488 connect(this, SIGNAL(tfready(QImage &)), tf_widget, SLOT(setTFImage(QImage &)));
00489
00490 connect(this, SIGNAL(histogram_changed(QList<int> &)), m_editor, SLOT(setHistogram(QList<int> &)));
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 QTimer::singleShot(50, this, SLOT(setDefault3()));
00502 }
00503
00504 void GradientWidget::setTransferFunction(QImage &tf_img)
00505 {
00506 m_transfer_function = tf_img;
00507 emit tfready(m_transfer_function);
00508 }
00509
00510 void GradientWidget::setGradientStops(const QGradientStops &stops)
00511 {
00512 m_stops.clear();
00513 m_editor->setGradientStops(stops);
00514 update();
00515 }
00516
00517 void GradientWidget::setDefault(int config)
00518 {
00519 QGradientStops stops;
00520 QPolygonF points;
00521 switch (config) {
00522
00523 case 1:
00524 stops << QGradientStop(0.00, QColor::fromRgba(0x00000000));
00525 stops << QGradientStop(1.00, QColor::fromRgba(0x00000000));
00526 break;
00527
00528 case 2:
00529 stops << QGradientStop(0.00, QColor::fromRgba(0xff000000));
00530 stops << QGradientStop(1.00, QColor::fromRgba(0xff000000));
00531 break;
00532
00533 case 3:
00534 stops << QGradientStop(0.00, QColor::fromRgba(0x00000000));
00535 stops << QGradientStop(1.00, QColor::fromRgba(0xffffffff));
00536 break;
00537
00538 case 4:
00539 stops << QGradientStop(0.00, QColor::fromRgba(0x00ff0000));
00540 stops << QGradientStop(1.00, QColor::fromRgba(0x00ff0000));
00541 break;
00542
00543 case 5:
00544 stops << QGradientStop(0.00, QColor::fromRgba(0x0000ff00));
00545 stops << QGradientStop(1.00, QColor::fromRgba(0x0000ff00));
00546 break;
00547
00548 case 6:
00549 stops << QGradientStop(0.00, QColor::fromRgba(0x000000ff));
00550 stops << QGradientStop(1.00, QColor::fromRgba(0x000000ff));
00551 break;
00552
00553 case 7:
00554 stops << QGradientStop(0.00, QColor::fromRgba(0xffff0000));
00555 stops << QGradientStop(0.50, QColor::fromRgba(0xff00ff00));
00556 stops << QGradientStop(1.00, QColor::fromRgba(0xff0000ff));
00557
00558
00559 break;
00560
00561 case 8:
00562 stops << QGradientStop(0.00, QColor::fromRgba(0xffffffff));
00563 stops << QGradientStop(1.00, QColor::fromRgba(0xffffffff));
00564 break;
00565 default:
00566 qWarning("bad default: %d\n", config);
00567 break;
00568 }
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 m_editor->setGradientStops(stops);
00579
00580
00581 }
00582
00583
00584 void GradientWidget::rendertf(const QGradientStops &stops)
00585 {
00586 m_stops = stops;
00587
00588 QImage tf_img = QImage(256, 256, QImage::Format_ARGB32_Premultiplied);
00589 tf_img.fill(0);
00590
00591 QLinearGradient lg = QLinearGradient(0, 0, 255, 0);
00592
00593 for (int i=0; i<stops.size(); ++i) {
00594 QColor c = stops.at(i).second;
00595 lg.setColorAt(stops.at(i).first, QColor(c.red(), c.green(), c.blue()));
00596 }
00597
00598 QPainter p(&tf_img);
00599
00600 p.fillRect(rect(), lg);
00601
00602 QGradient fade;
00603
00604 p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
00605 fade = QLinearGradient(0, 0, 255, 0);
00606
00607 for (int i=0; i<m_stops.size(); ++i)
00608 {
00609 fade.setColorAt(m_stops.at(i).first, m_stops.at(i).second);
00610 }
00611
00612
00613 p.setBrush(fade);
00614 p.drawRect(rect());
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639 m_transfer_function = tf_img;
00640 emit tfready(m_transfer_function);
00641
00642
00643 update();
00644 }
00645
00646
00647 GradientRenderer::GradientRenderer(QWidget *parent) : QGLWidget(parent)
00648
00649 {
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
00667 }
00668
00669 void GradientRenderer::setGradientStops(const QGradientStops &stops)
00670 {
00671 m_stops = stops;
00672 update();
00673 }
00674 void GradientRenderer::initializeGL()
00675 {
00676
00677
00678 qglClearColor(QColor::fromRgb(255,255,255));
00679 glShadeModel (GL_FLAT);
00680 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
00681 glutInitDisplayMode(GLUT_RGBA);
00682 gluOrtho2D(0.0, 256.0, 0.0, 512.0);
00683 }
00684
00685 void GradientRenderer::paintGL()
00686 {
00687 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00688
00689 glLoadIdentity();
00690
00691 glTranslated(0.0, 0.0, 0.0);
00692
00693
00694 QPointF v00 = QPointF(10.0, 0.0);
00695 QPointF v01 = QPointF(200.0, 128.0);
00696 QPointF v02 = QPointF(100.0, 256.0);
00697 QPointF v03 = QPointF(20.0, 384.0);
00698 QPointF v04 = QPointF(140.0, 512.0);
00699 QColor line_color0 = QColor(255,0,0,255);
00700
00701
00702 QList<QPointF> vertices0;
00703 vertices0.append(v00);
00704 vertices0.append(v01);
00705 vertices0.append(v02);
00706 vertices0.append(v03);
00707 vertices0.append(v04);
00708
00709
00710 QPointF v10 = QPointF(100.0, 0.0);
00711 QPointF v11 = QPointF(150.0, 128.0);
00712 QPointF v12 = QPointF(200.0, 256.0);
00713 QPointF v13 = QPointF(126.0, 384.0);
00714 QPointF v14 = QPointF(10.0, 512.0);
00715 QColor line_color1 = QColor(0,0,255,255);
00716
00717
00718 QList<QPointF> vertices1;
00719 vertices1.append(v10);
00720 vertices1.append(v11);
00721 vertices1.append(v12);
00722 vertices1.append(v13);
00723 vertices1.append(v14);
00724
00725
00726
00727 typedef QPair<QList<QPointF>,QColor> ParralelCoordinatesLine;
00728 typedef QList<ParralelCoordinatesLine> ParallelCoordinatesLinesList;
00729
00730 ParallelCoordinatesLinesList pc_lines_list;
00731 pc_lines_list.append(qMakePair(vertices0,line_color0));
00732 pc_lines_list.append(qMakePair(vertices1,line_color1));
00733
00734 QListIterator<ParralelCoordinatesLine> pc_lineslist_i(pc_lines_list);
00735 ParralelCoordinatesLine pc_line;
00736 QList<QPointF> pc_line_vertices;
00737 QColor pc_line_color;
00738 while(pc_lineslist_i.hasNext())
00739 {
00740 pc_line = pc_lineslist_i.next();
00741 pc_line_vertices = pc_line.first;
00742 pc_line_color = pc_line.second;
00743
00744
00745 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00746
00747
00748 qglColor(pc_line_color);
00749
00750
00751 glBegin(GL_POLYGON);
00752 QListIterator<QPointF> i(pc_line_vertices);
00753 QPointF poly_vertex;
00754 while (i.hasNext())
00755 {
00756 poly_vertex = (QPointF)i.next();
00757
00758
00759 if(i.hasNext())
00760 glEdgeFlag(GL_TRUE);
00761 else
00762 glEdgeFlag(GL_FALSE);
00763
00764 glVertex2f(poly_vertex.x(),poly_vertex.y());
00765 }
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778 glEnd();
00779 }
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807 glFlush ();
00808
00809 }
00810
00811 void GradientRenderer::resizeGL(int width, int height)
00812 {
00813 int side = qMin(width, height);
00814
00815 glViewport (0, 0, (GLsizei) width, (GLsizei) height);
00816 glMatrixMode (GL_PROJECTION);
00817 glLoadIdentity ();
00818 }
00819
00820 void GradientRenderer::mousePressEvent(QMouseEvent *event)
00821 {
00822 }
00823
00824 void GradientRenderer::mouseMoveEvent(QMouseEvent *event)
00825 {
00826 }