├── .gitignore ├── LICENSE ├── QHeatMap.pro ├── README.md ├── captures ├── capture-1.png └── capture-2.png ├── include ├── global.h ├── gradientpalette.h └── heatmapper.h ├── lib ├── gradientpalette.cpp ├── heatmapper.cpp └── lib.pro └── test ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h └── test.pro /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | moc_* 6 | 7 | # Compiled Dynamic libraries 8 | *.so 9 | *.so.* 10 | *.dylib 11 | 12 | # Compiled Static libraries 13 | *.lai 14 | *.la 15 | *.a 16 | 17 | Makefile 18 | QHeatMap 19 | test/test 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Dianchun Huang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /QHeatMap.pro: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | # Automatically generated by qmake (2.01a) Sat May 25 02:01:48 2013 3 | ###################################################################### 4 | 5 | TEMPLATE = subdirs 6 | SUBDIRS = lib 7 | SUBDIRS += test 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | QHeatMap 2 | ======== 3 | 4 | Generate Heat map in Qt. 5 | 6 | Screen Capture 7 | -------------- 8 | 9 | ![Screen Capture 1](https://github.com/pbesedm/QHeatMap/blob/master/captures/capture-1.png?raw=true) 10 | 11 | ![Screen Capture 2](https://github.com/pbesedm/QHeatMap/blob/master/captures/capture-2.png?raw=true) 12 | -------------------------------------------------------------------------------- /captures/capture-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pbesedm/QHeatMap/67159c4dec09c790b82019f21b2fe9cfb06b56f4/captures/capture-1.png -------------------------------------------------------------------------------- /captures/capture-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pbesedm/QHeatMap/67159c4dec09c790b82019f21b2fe9cfb06b56f4/captures/capture-2.png -------------------------------------------------------------------------------- /include/global.h: -------------------------------------------------------------------------------- 1 | /*==================================================================== 2 | * Filename: global.h 3 | * Version: 4 | * Author: Dianchun Huang 5 | * 6 | * Copyright (c) 2013 Dianchun Huang (simpleotter23@gmail.com) 7 | * 8 | * Created at: Tue Jul 9 22:00:51 2013 9 | * Modified at: Tue Jul 9 22:02:15 2013 10 | * Description: 11 | *==================================================================*/ 12 | #ifndef _GLOBAL_H_ 13 | #define _GLOBAL_H_ 14 | 15 | #include 16 | 17 | #if defined(QHEATMAP_DLL_LIBRARY) 18 | # define QHEATMAP_DLL_EXPORT Q_DECL_EXPORT 19 | #else 20 | # define QHEATMAP_DLL_EXPORT 21 | #endif 22 | 23 | #endif /* _GLOBAL_H_ */ 24 | -------------------------------------------------------------------------------- /include/gradientpalette.h: -------------------------------------------------------------------------------- 1 | /*==================================================================== 2 | * Filename: gradientpalette.h 3 | * Version: 4 | * Author: Dianchun Huang 5 | * 6 | * Copyright (c) 2013 Dianchun Huang (simpleotter23@gmail.com) 7 | * 8 | * Created at: Sat May 25 08:38:15 2013 9 | * Modified at: Sat May 25 08:53:39 2013 10 | * Description: 11 | *==================================================================*/ 12 | #ifndef _GRADIENTPALETTE_H_ 13 | #define _GRADIENTPALETTE_H_ 14 | 15 | #include 16 | 17 | QT_BEGIN_NAMESPACE 18 | class QImage; 19 | QT_END_NAMESPACE 20 | 21 | class GradientPalette 22 | { 23 | public: 24 | GradientPalette(int width); 25 | ~GradientPalette(); 26 | 27 | void setColorAt(qreal index, const QColor &color); 28 | QColor getColorAt(qreal index); 29 | 30 | private: 31 | // 作为调色板的画布 32 | QImage *canvas_; 33 | // 线性渐变 34 | QLinearGradient gradient_; 35 | // 宽度 36 | int width_; 37 | }; 38 | 39 | #endif /* _GRADIENTPALETTE_H_ */ 40 | -------------------------------------------------------------------------------- /include/heatmapper.h: -------------------------------------------------------------------------------- 1 | /*==================================================================== 2 | * Filename: heatmapper.h 3 | * Version: 4 | * Author: Dianchun Huang 5 | * 6 | * Copyright (c) 2013 Dianchun Huang (simpleotter23@gmail.com) 7 | * 8 | * Created at: Thu May 23 23:06:27 2013 9 | * Modified at: Tue Jul 9 23:12:59 2013 10 | * Description: 11 | *==================================================================*/ 12 | #ifndef _HEATMAPPER_H_ 13 | #define _HEATMAPPER_H_ 14 | 15 | #include "global.h" 16 | #include 17 | 18 | QT_BEGIN_NAMESPACE 19 | class QImage; 20 | QT_END_NAMESPACE 21 | 22 | class GradientPalette; 23 | 24 | class QHEATMAP_DLL_EXPORT HeatMapper 25 | { 26 | public: 27 | HeatMapper(QImage *image, GradientPalette *palette, int radius, int opacity); 28 | virtual ~HeatMapper(); 29 | 30 | void save(const QString &fname); 31 | void addPoint(int x, int y); 32 | void setPalette(GradientPalette *palette); 33 | int getCount(int x, int y); 34 | void colorize(int x, int y); 35 | void colorize(); 36 | 37 | virtual void drawAlpha(int x, int y, int count, bool colorize_now = true); 38 | 39 | protected: 40 | virtual void colorize(int left, int top, int right, int bottom); 41 | void redraw(); 42 | 43 | private: 44 | int increase(int x, int y, int delta = 1); 45 | 46 | private: 47 | // 存储点频率的数组,大小和图像一样 48 | QVector data_; 49 | // 用于存储渐变透明数据的图像副本 50 | QImage *alphaCanvas_; 51 | // 用于显示输出的图像 52 | QImage *mainCanvas_; 53 | // 调色板 54 | GradientPalette *palette_; 55 | // 半径 56 | int radius_; 57 | // 不透明度 58 | int opacity_; 59 | // 最大命名数 60 | qreal max_; 61 | // 图像宽度 62 | int width_; 63 | // 图像高度 64 | int height_; 65 | }; 66 | 67 | #endif /* _HEATMAPPER_H_ */ 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /lib/gradientpalette.cpp: -------------------------------------------------------------------------------- 1 | /*==================================================================== 2 | * Filename: gradientpalette.cpp 3 | * Version: 4 | * Author: Dianchun Huang 5 | * 6 | * Copyright (c) 2013 Dianchun Huang (simpleotter23@gmail.com) 7 | * 8 | * Created at: Sat May 25 08:45:12 2013 9 | * Modified at: Sat Jul 6 13:30:56 2013 10 | * Description: 11 | *==================================================================*/ 12 | #include "gradientpalette.h" 13 | #include 14 | #include 15 | #include 16 | 17 | /* 18 | * 构造函数 19 | * @param width 渐变调色板宽度 20 | */ 21 | GradientPalette::GradientPalette(int width) 22 | : gradient_(0, 0, width, 1), 23 | width_(width) 24 | { 25 | canvas_ = new QImage(width, 1, QImage::Format_ARGB32); 26 | } 27 | 28 | /* 29 | * 析构函数 30 | */ 31 | GradientPalette::~GradientPalette() 32 | { 33 | delete canvas_; 34 | canvas_ = NULL; 35 | } 36 | 37 | /* 38 | * 用指定颜色在指定位置创建一个停止点 39 | * @param index 指定位置,对应位置为 (0, index) 40 | * @param color 颜色 41 | */ 42 | void GradientPalette::setColorAt(qreal index, const QColor &color) 43 | { 44 | gradient_.setColorAt(index, color); 45 | 46 | QPainter painter(canvas_); 47 | painter.setBrush(gradient_); 48 | painter.setPen(Qt::NoPen); 49 | painter.fillRect(canvas_->rect(), gradient_); 50 | } 51 | 52 | /* 53 | * 获得指定点颜色值 54 | * @param index 取值位置 55 | * @return 返回指定索引处的颜色值 56 | */ 57 | QColor GradientPalette::getColorAt(qreal index) 58 | { 59 | index -= 1; 60 | if (index > width_) 61 | return Qt::color0; 62 | return canvas_->pixel(index, 0); 63 | } 64 | -------------------------------------------------------------------------------- /lib/heatmapper.cpp: -------------------------------------------------------------------------------- 1 | /*==================================================================== 2 | * Filename: heatmapper.cpp 3 | * Version: 4 | * Author: Dianchun Huang 5 | * 6 | * Copyright (c) 2013 Dianchun Huang (simpleotter23@gmail.com) 7 | * 8 | * Created at: Thu May 23 23:39:03 2013 9 | * Modified at: Tue Jul 9 23:45:21 2013 10 | * Description: 11 | *==================================================================*/ 12 | #include "heatmapper.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "gradientpalette.h" 19 | 20 | /* 21 | * 构造函数 22 | * @param image 用于显示输出的图像 23 | * @param radius 半径,决定了径向渐变的大小 24 | * @param opacity 不透明度,取值范围为[0, 100] 25 | */ 26 | HeatMapper::HeatMapper(QImage *image, GradientPalette *palette, 27 | int radius, int opacity) 28 | : radius_(radius), opacity_(opacity), max_(1) 29 | { 30 | Q_ASSERT(image); 31 | Q_ASSERT(palette); 32 | 33 | palette_ = palette; 34 | 35 | mainCanvas_ = image; 36 | alphaCanvas_ = new QImage(image->size(), QImage::Format_ARGB32); 37 | Q_ASSERT(alphaCanvas_); 38 | alphaCanvas_->fill(QColor(0, 0, 0, 0)); 39 | 40 | width_ = image->width(); 41 | height_ = image->height(); 42 | data_.resize(width_ * height_); 43 | data_.fill(0); 44 | } 45 | 46 | HeatMapper::~HeatMapper() 47 | {} 48 | 49 | /* 50 | * 增加指定坐标点的命中次数 51 | * @param x 横坐标 52 | * @param y 纵坐标 53 | * @param delta 增加的次数值 54 | * @return 返回更新后的命中次数 55 | */ 56 | int HeatMapper::increase(int x, int y, int delta) 57 | { 58 | int index = (y - 1) * width_ + (x - 1); 59 | data_[index] += delta; 60 | return data_[index]; 61 | } 62 | 63 | /* 64 | * 将图像保存到文件 65 | * @param fname 文件名 66 | */ 67 | void HeatMapper::save(const QString &fname) 68 | { 69 | 70 | } 71 | 72 | /* 73 | * 添加一个数据点 74 | * @param x 横坐标 75 | * @param y 纵坐标 76 | */ 77 | void HeatMapper::addPoint(int x, int y) 78 | { 79 | if (x <= 0 || y <= 0 || x > width_ || y > height_) 80 | return; 81 | 82 | int count = increase(x, y); 83 | 84 | if (max_ < count) { 85 | max_ = count; 86 | redraw(); 87 | return; 88 | } 89 | 90 | drawAlpha(x, y, count); 91 | } 92 | 93 | /* 94 | * 根据最大命中次数重绘整个图像,此方法会产生余辉效果 95 | */ 96 | void HeatMapper::redraw() 97 | { 98 | QColor color(0, 0, 0, 0); 99 | alphaCanvas_->fill(color); 100 | mainCanvas_->fill(color); 101 | 102 | int size = data_.size(); 103 | for (int i = 0; i < size; ++i) { 104 | if (0 == data_[i]) 105 | continue; 106 | drawAlpha(i % width_ + 1, i / width_ + 1, data_[i], false); 107 | } 108 | colorize(); 109 | } 110 | 111 | /* 112 | * 设置调色板 113 | * @param palette 调色板对象指针 114 | */ 115 | void HeatMapper::setPalette(GradientPalette *palette) 116 | { 117 | Q_ASSERT(palette); 118 | 119 | if (palette) 120 | palette_ = palette; 121 | } 122 | 123 | /* 124 | * 获得指定点的命中次数 125 | */ 126 | int HeatMapper::getCount(int x, int y) 127 | { 128 | if (x < 0 || y < 0) 129 | return 0; 130 | return data_[(y - 1) * width_ + (x - 1)]; 131 | } 132 | 133 | /* 134 | * 绘制透明径向渐变 135 | * @param x 横坐标 136 | * @param y 纵坐标 137 | * @param count 被命中次数 138 | * @param colorize_now 是否调用着色方法 139 | */ 140 | void HeatMapper::drawAlpha(int x, int y, int count, bool colorize_now) 141 | { 142 | int alpha = int(qreal(count * 1.0 / max_)*255); 143 | QRadialGradient gradient(x, y, radius_); 144 | gradient.setColorAt(0, QColor(0, 0, 0, alpha)); 145 | gradient.setColorAt(1, QColor(0, 0, 0, 0)); 146 | 147 | QPainter painter(alphaCanvas_); 148 | painter.setPen(Qt::NoPen); 149 | painter.setBrush(gradient); 150 | painter.drawEllipse(QPoint(x, y), radius_, radius_); 151 | 152 | if (colorize_now) 153 | colorize(x, y); 154 | } 155 | 156 | /* 157 | * 重载方法,着色 158 | */ 159 | void HeatMapper::colorize() 160 | { 161 | colorize(0, 0, width_, height_); 162 | } 163 | 164 | /* 165 | * 重载方法,着色 166 | * @param x 横坐标 167 | * @param y 纵坐标 168 | * @param subArea 透明径向渐变区域 169 | */ 170 | void HeatMapper::colorize(int x, int y) 171 | { 172 | int left = x - radius_; 173 | int top = y - radius_; 174 | int right = x + radius_; 175 | int bottom = y + radius_; 176 | QColor color; 177 | 178 | if (left < 0) 179 | left = 0; 180 | 181 | if (top < 0) 182 | top = 0; 183 | 184 | if (right > width_) 185 | right = width_; 186 | 187 | if (bottom > height_) 188 | bottom = height_; 189 | 190 | colorize(left, top, right, bottom); 191 | } 192 | 193 | /* 194 | * 重载函数,实际的着色操作在本方法 195 | * @param left 左上角横坐标 196 | * @param top 左上角纵坐标 197 | * @param right 右下角横坐标 198 | * @param bottom 右下角纵坐标 199 | */ 200 | void HeatMapper::colorize(int left, int top, int right, int bottom) 201 | { 202 | int alpha = 0; 203 | int finalAlpha = 0; 204 | QColor color; 205 | for (int i = left; i < right; ++i) { 206 | for (int j = top; j < bottom; ++j) { 207 | alpha = qAlpha(alphaCanvas_->pixel(i, j)); 208 | if (!alpha) 209 | continue; 210 | finalAlpha = (alpha < opacity_ ? alpha : opacity_); 211 | color = palette_->getColorAt(alpha); 212 | mainCanvas_->setPixel(i, j, qRgba(color.red(), 213 | color.green(), 214 | color.blue(), 215 | finalAlpha)); 216 | } 217 | } 218 | } 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | -------------------------------------------------------------------------------- /lib/lib.pro: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | # Automatically generated by qmake (2.01a) Sat May 25 01:58:33 2013 3 | ###################################################################### 4 | 5 | QT += core gui 6 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 7 | 8 | TEMPLATE = lib 9 | TARGET = qheatmap 10 | DEPENDPATH += . 11 | INCLUDEPATH += . ../include/ 12 | 13 | unix: { 14 | MOC_DIR += /tmp 15 | OBJECTS_DIR += /tmp 16 | } 17 | 18 | DEFINES += QHEATMAP_DLL_LIBRARY 19 | 20 | # Input 21 | SOURCES += heatmapper.cpp ./gradientpalette.cpp 22 | -------------------------------------------------------------------------------- /test/main.cpp: -------------------------------------------------------------------------------- 1 | /*==================================================================== 2 | * Filename: main.cpp 3 | * Version: 4 | * Author: Dianchun Huang 5 | * 6 | * Copyright (c) 2013 Dianchun Huang (simpleotter23@gmail.com) 7 | * 8 | * Created at: Thu May 23 22:42:59 2013 9 | * Modified at: Wed Jul 10 19:11:47 2013 10 | * Description: 11 | *==================================================================*/ 12 | #include 13 | #include "mainwindow.h" 14 | 15 | int main(int argc, char *argv[]) 16 | { 17 | QApplication app(argc, argv); 18 | 19 | MainWindow w; 20 | w.show(); 21 | 22 | return app.exec(); 23 | } 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /test/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | /*==================================================================== 2 | * Filename: mainwindow.cpp 3 | * Version: 4 | * Author: Dianchun Huang 5 | * 6 | * Copyright (c) 2013 Dianchun Huang (simpleotter23@gmail.com) 7 | * 8 | * Created at: Thu May 23 22:42:06 2013 9 | * Modified at: Tue Jul 9 22:10:59 2013 10 | * Description: 11 | *==================================================================*/ 12 | #include "mainwindow.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "heatmapper.h" 19 | #include "gradientpalette.h" 20 | 21 | /* 22 | * 构造函数 23 | */ 24 | MainWindow::MainWindow(QWidget *parent) 25 | : QWidget(parent) 26 | { 27 | palette_ = new GradientPalette(DEFAULT_WIDTH); 28 | 29 | palette_->setColorAt(0.45, Qt::blue); 30 | palette_->setColorAt(0.55, Qt::cyan); 31 | palette_->setColorAt(0.65, Qt::green); 32 | palette_->setColorAt(0.85, Qt::yellow); 33 | palette_->setColorAt(1.0, Qt::red); 34 | 35 | canvas_ = new QImage(CANVAS_WIDTH, CANVAS_HEIGHT, QImage::Format_ARGB32); 36 | canvas_->fill(QColor(0, 0, 0, 0)); 37 | mapper_ = new HeatMapper(canvas_, palette_, DEFAULT_RADIUS, DEFAULT_OPACITY); 38 | this->setFixedSize(CANVAS_WIDTH, CANVAS_HEIGHT); 39 | } 40 | 41 | MainWindow::~MainWindow() 42 | { 43 | delete mapper_; 44 | delete palette_; 45 | } 46 | 47 | /* 48 | * 绘图方法,当窗口刷新时该方法会被调用 49 | */ 50 | void MainWindow::paintEvent(QPaintEvent *) 51 | { 52 | QPainter painter(this); 53 | painter.drawImage(0, 0, *canvas_); 54 | } 55 | 56 | /* 57 | * 该方法用于向绘图对象添加一个数据点 58 | */ 59 | void MainWindow::mouseReleaseEvent(QMouseEvent *e) 60 | { 61 | if (NULL == mapper_) 62 | return; 63 | 64 | mapper_->addPoint(e->x(), e->y()); 65 | this->update(); 66 | } 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /test/mainwindow.h: -------------------------------------------------------------------------------- 1 | /*==================================================================== 2 | * Filename: mainwindow.h 3 | * Version: 4 | * Author: Dianchun Huang 5 | * 6 | * Copyright (c) 2013 Dianchun Huang (simpleotter23@gmail.com) 7 | * 8 | * Created at: Thu May 23 22:20:02 2013 9 | * Modified at: Wed Jul 10 19:12:07 2013 10 | * Description: 11 | *==================================================================*/ 12 | #ifndef _MAINWINDOW_H_ 13 | #define _MAINWINDOW_H_ 14 | 15 | #include 16 | 17 | QT_BEGIN_NAMESPACE 18 | class QImage; 19 | QT_END_NAMESPACE 20 | 21 | class HeatMapper; 22 | class GradientPalette; 23 | 24 | class MainWindow : public QWidget 25 | { 26 | public: 27 | enum { 28 | CANVAS_WIDTH = 1000, 29 | CANVAS_HEIGHT = 700, 30 | DEFAULT_RADIUS = 60, 31 | DEFAULT_OPACITY = 128, 32 | DEFAULT_WIDTH = 255 33 | }; 34 | 35 | explicit MainWindow(QWidget *parent = 0); 36 | virtual ~MainWindow(); 37 | 38 | protected: 39 | void paintEvent(QPaintEvent *); 40 | void mouseReleaseEvent(QMouseEvent *e); 41 | 42 | private: 43 | // 绘图对象指针 44 | HeatMapper *mapper_; 45 | // 用于显示输出的图像 46 | QImage *canvas_; 47 | // 调色板 48 | GradientPalette *palette_; 49 | }; 50 | 51 | #endif /* _MAINWINDOW_H_ */ 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /test/test.pro: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | # Automatically generated by qmake (2.01a) Sat May 25 01:59:45 2013 3 | ###################################################################### 4 | 5 | QT += core gui 6 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 7 | 8 | TEMPLATE = app 9 | TARGET = test 10 | DEPENDPATH += . ../lib 11 | INCLUDEPATH += . ../include 12 | 13 | unix: { 14 | MOC_DIR += /tmp 15 | OBJECTS_DIR += /tmp 16 | } 17 | 18 | # Input 19 | HEADERS += mainwindow.h ../include/heatmapper.h ../include/gradientpalette.h 20 | SOURCES += main.cpp mainwindow.cpp ../lib/heatmapper.cpp ../lib/gradientpalette.cpp 21 | --------------------------------------------------------------------------------