电子放大这个功能思考了很久,也是一直拖到近期才静下心来完整这个小功能,这个功能的前提,主要得益于之前把滤镜打通了,玩出花样来了,只要传入对应的滤镜字符串,就可以实现各种各样的效果,然后查阅滤镜手册过程中,发现有个裁剪crop的滤镜,和要做的电子放大效果完全一样,就是将指定的某个区域放大显示,这不就是电子放大吗?加上之前就解决了如何通过用户鼠标按下的点转换成视频真实的坐标,两者一个结合,这不就是水到渠成的事情?所以很多时候就是这样搞着搞着,问题自然而然就解决了。
大致步骤如下:
其实电子放大除了可以通过滤镜来实现,也可以直接opengl这边处理,无奈自己opengl水平还没入门,根本不知道怎么搞,所以才想着直接源头就滤镜处理好。通过对比各个厂家做的电子放大功能,发现海康的实现更加鸡贼,完全没有用滤镜,也没有用opengl绘制局部数据,而是直接将整个视频放大,放大到当前画面区域几乎就是刚才选取的区域,把整个视频面板放大到合适,然后放在一个拖动或者滚动区域中,相当于看图软件中的很大分辨率的图片,然后再通过手按下还可以一点点的移动视频画面,其实就是一个控件在move,这种方式很取巧,而且还能用手按着拖动进行调整查看画面,也是蛮好的一种思路,唯一要做的就是计算好用户选取的区域和将要放大的尺寸。
void AbstractVideoWidget::getPoint(QEvent *event)
{
//正在运行中的视频或者设置了图片
if ((isRunning || !image.isNull()) && !onlyAudio) {
QMouseEvent *e = (QMouseEvent *)event;
QPoint p = hwndWidget->mapFromParent(e->pos());
//过滤在绘图区域里面
if (hwndWidget->rect().contains(p)) {
int w = videoWidth;
int h = videoHeight;
WidgetHelper::rotateSize(rotate, w, h);
int x = (double)p.x() / hwndWidget->width() * w;
int y = (double)p.y() / hwndWidget->height() * h;
emit sig_receivePoint(event->type(), QPoint(x, y));
}
}
}
//关联鼠标按下用于电子放大
connect(this, SIGNAL(sig_receivePoint(int, QPoint)), this, SLOT(receivePoint(int, QPoint)));
void VideoWidget::receivePoint(int type, const QPoint &point)
{
if (!videoThread) {
return;
}
//处于电子放大阶段才处理(悬浮条按钮切换)
if (bannerWidget->getIsCrop()) {
//限定只有一个电子放大滤镜
foreach (GraphInfo graph, listGraph) {
if (graph.name == "crop") {
return;
}
}
//第一步: 鼠标按下开始记住坐标
//第二步: 鼠标移动绘制选取区域
//第三步: 鼠标松开发送裁剪滤镜
if (type == QEvent::MouseButtonPress) {
lastPoint = point;
} else if (type == QEvent::MouseMove) {
GraphInfo graph;
graph.name = "croptemp";
graph.rect = WidgetHelper::getRect(lastPoint, point);
graph.borderWidth = WidgetHelper::getBorderWidth(this);
this->setGraph(graph);
} else if (type == QEvent::MouseButtonRelease) {
GraphInfo graph;
graph.name = "crop";
graph.rect = WidgetHelper::getRect(lastPoint, point);
this->removeGraph("croptemp");
this->setGraph(graph);
}
}
}
void AbstractVideoWidget::setGraph(const GraphInfo &graph)
{
//存在则替换
bool exist = false;
int count = listGraph.count();
for (int i = 0; i < count; ++i) {
GraphInfo graphInfo = listGraph.at(i);
if (graphInfo.name == graph.name) {
exist = true;
listGraph[i] = graph;
emit sig_graphChanged();
return;
}
}
//不存在则插入
if (!exist) {
this->appendGraph(graph);
}
}
void AbstractVideoWidget::appendGraph(const GraphInfo &graph)
{
QMutexLocker locker(&mutex);
listGraph << graph;
this->update();
emit sig_graphChanged();
}
void AbstractVideoWidget::removeGraph(const QString &name)
{
QMutexLocker locker(&mutex);
int count = listGraph.count();
for (int i = 0; i < count; ++i) {
if (listGraph.at(i).name == name) {
listGraph.removeAt(i);
break;
}
}
this->update();
emit sig_graphChanged();
}
void AbstractVideoWidget::clearGraph()
{
QMutexLocker locker(&mutex);
listGraph.clear();
this->update();
emit sig_graphChanged();
}