用Qt(C++)实现如苹果般的亮屏效果
用Qt(C++)实现如苹果般的亮屏效果
苹果的亮屏效果可能有很多人没注意到,和其他大部分手机或电脑不同的是,苹果的亮屏特效不是简单的亮度变化,而是一个渐亮的过程。详细来说就是,图片中较亮的部分先显示出来,而后渐变的显示较暗的地方,最后整个图片完全显示。
那么,Qt该如何实现类似效果?
先看最终效果:
图中是一束灯光,点亮时光束中间较亮的部位显现出来,再带动其他部位显现,这个效果暂且成为“渐亮”。
用到
想要实现此效果,首先需要了解到的Qt函数:
//该函数用于设置图片中(x,y)点的rgb值
void QImage::setPixel(int x, int y, uint index_or_rgb);
思路
可以很明显的看出,点亮和关屏都不是一瞬间完成的,所以,我们首先需要一个计时器来控制该过程。而后我们需要确定该算法的索引,也就是说,假设这个过程需要100帧,那么我们肯定需要一个变量用于记录这个过程执行的进度。再根据进度,计算出当前帧的所有像素点应显示的内容,从而得到这一帧的图片。
如果是普通的亮度计算的话,很简单,只需要每一个像素的RGB值分别和亮度系数相乘即可。亮度系数如果在0-1区间内的话,那么对应的就是从完全黑的图片显示出图片本身的一个过程。
例如:
下边这个RGB颜色值为深绿色:
将RGB三个数字乘以1.5,就会变成下边这个颜色:
这就是亮度调节的基本原理。
所以,要实现渐亮,就要先显现出亮度大于阈值的像素,随着时间推移,阈值越来越大,显示的像素越来越多。
那么,如何获取某像素的亮度值呢?
当RGB三个值均为255时,亮度最大,显白色,当三个值均为0时,亮度最小,显黑色。那么我们可以获取RGB三值的平均数,将其与255相除,规定其为亮度值,也就是说:亮度值=(red+green+blue)/3/255
,化简后得:亮度值=(red+green+blue)/765
。
到此,基本的原理就搞清楚了,但是这里仍然还有一个问题,等我们先实现后再说明。
实现
跟着思路,写下如下代码:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QRgb>
#include <QImage>
#include <QTimer>
#define PASS 0.3;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
p.load(":/b.jpg");
double size=0.4; //图片缩放系数
p=p.scaled(p.width()*size,p.height()*size);
ui->label->setPixmap(QPixmap::fromImage(p));
speed=0;
timer=new QTimer;
timer->setInterval(1);
i=0;
connect(timer,&QTimer::timeout,[=](){
i+=speed;
MainWindow::update(i);
if(i>100 || i<0){
i=0;
timer->stop();
}
});
on_pushButton_clicked();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::update(int position) //参数为0-100,若从0开始,则逐步变亮,若从100开始,则逐步变暗
{
QImage t(p);
double bright=double(position)/100; //亮度系数
bright=(bright>1)?1:bright;
bright=(bright<0)?0:bright;
double flag=-bright+1; //渐亮需要的阈值
setWindowTitle("亮度:" + QString::number(bright)+
"阈值:"+ QString::number(flag));
for(int x=0;x<p.width();x++){
for (int y=0;y<p.height();y++) {
QColor c(p.pixel(x,y));
double b=double(c.red()+c.green()+c.blue())/765; //计算当前像素的亮度
if(b>flag){ //判断亮度与阈值的大小关系
//若亮度大于阈值,将该像素乘以亮度系数
c.setRgb((int(c.red()*bright)>255)?255:int(c.red()*bright),
(int(c.green()*bright)>255)?255:int(c.green()*bright),
(int(c.blue()*bright)>255)?255:int(c.blue()*bright));
}else {
//若亮度小于阈值,则显示黑色像素,这部分会导致出现问题,后边会替换。
c.setRgb(0,0,0);
}
t.setPixel(x,y,c.rgb());//将像素写入临时变量
}
}
ui->label->setPixmap(QPixmap::fromImage(t));//将计算好的一帧显示在label上
}
void MainWindow::on_pushButton_clicked()
{
//灭
i=100;
speed=-3;
timer->start();
}
void MainWindow::on_pushButton_2_clicked()
{
//亮
i=0;
speed=3;
timer->start();
}
如下效果:
可见效果虽然大体实现了,但是还是很差劲的,渐亮的边缘过于生硬,这就是我上边提到的问题,怎么解决呢?
问题
先分析出现这个问题的原因,代码中将阈值以外的像素直接置为黑色了,其实应当有一个过度的过程,可阈值相差不多的边缘,可以渐变直到和阈值相差较大,最终变为黑色。
所以,将像素置为黑色部分的代码替换为以下代码:
else {
//c.setRgb(0,0,0);
double a=1.0-(flag-b)*10; //获取加权亮度系数,亮度越大,系数越大,亮度越小,系数越小,最小到0
a=(a<0)?0:a;
c.setRgb((int(c.red()*bright*a)>255)?255:int(c.red()*bright*a),
(int(c.green()*bright*a)>255)?255:int(c.green()*bright*a),
(int(c.blue()*bright*a)>255)?255:int(c.blue()*bright*a));
}
修改后的效果:
很明显,柔和了许多。
到此为止基本上效果已经实现了,当然,肯定没有苹果那么丝滑,只是形似。
用Qt(C++)实现如苹果般的亮屏效果的更多相关文章
- MSM8909的触摸屏驱动导致的熄屏后重新亮屏速度慢的原因!【转】
转自:https://blog.csdn.net/kk20000/article/details/83041081 使用的汇顶的触摸驱动的时候会重新亮屏速度慢3秒,而在使用另外一个敦泰触摸驱动的时候没 ...
- Android让手机主动亮屏的代码
我们在做电子阅读器的时候可能会要求屏幕保持常亮,不希望它熄灭.它的原理也是利用系统服务,来操纵底层设备. 一.系统服务——PowerManager PowerManager.java就是管理我们电源方 ...
- Android Notification实现推送消息过程中接受到消息端有声音及震动及亮屏提示
在Android Notification状态栏通知一文中,简单实现了消息的推送效果,这里就接着上文说一下,当用户接受到消息时的提示效果 // 5-增加震动及声音及亮屏 notification.de ...
- iOS亮屏解锁命令【iOS自动化测试】--使用ssh
前提:iOS越狱手机一个 越狱方法:使用pp助手, 爱思助手等 1.从Cydia安装以下软件: AppSync for iOSx(可安装破解软件).afc2add补丁(可访问整个iOS设备的系统文件) ...
- python3:判断手机的亮屏状态
在用python对手机做一些自动化操作时,常常会判断手机的亮屏状态,知晓手机的亮屏状态后才好做进一步的动作,如给屏幕解锁等. 用于了解手机的亮屏情况,有一个adb命令可用: adb shell du ...
- Android 动态注册 亮屏、息屏广播
/***************************************************************************** * Android 动态注册 亮屏.息屏广 ...
- Qt无边框窗体-模拟模态窗体抖动效果
目录 一.概述 二.效果展示 三.功能实现 四.相关文章 原文链接:Qt无边框窗体-模拟模态窗体抖动效果 一.概述 用Qt开发windows客户端界面确实是一大利器,兼顾性能的同时,速度相对来说也不错 ...
- 搭建Android+QT+OpenCV环境,实现“单色图片着色”效果
OpenCV是我们大家非常熟悉的图像处理开源类库:在其新版本将原本在Contrib分库中的DNN模块融合到了主库中,并且更新了相应文档.这样我们就能够非常方便地利用OpenCV实 ...
- 通过adb操作安卓亮屏、设置背光亮度、解锁、打开app
亮屏 adb shell inputkeyevent 26 keyevent 26表示点击power Android adb 点亮和关闭屏幕的命令 # kernel休眠 echo mem > / ...
随机推荐
- 如何用Eggjs从零开始开发一个项目(3)
上一篇中我们编写了用户注册登录.登录的代码,学习了如何进行用户的认证(JWT),如何安全地存储用的密码(hash).这一篇我们有以下2个任务: 获取token中的数据: 通过model来同步数据库. ...
- Docker daemon socket权限不足
一.概述 普通用户执行命令:docker ps报错,具体信息如下: docker: Got permission denied while trying to connect to the Docke ...
- 算法 - 链表操作思想 && case
算法 - 链表操作题目套路 前面这一篇文章主要讲链表操作时候的实操解决方式,本文从本质讲解链表操作的元信息,学完后,再也不怕链表操作题目了. 1.链表的基本操作 链表的基本操作无外乎插入,删除,遍历 ...
- es6 快速入门 系列
es6 快速入门(未完结,持续更新中...) 前言 为什么要学习es6 es6对于所有javaScript开发者来说,非常重要 未来,es6将构成javaScript应用程序的基础 es6中很多特性, ...
- 后端程序员之路 44、Redis结合protobuf
protobuf序列化速度不错,在往Redis里存对象时,用protobuf序列化可以节省内存,省去写序列化反序列化代码的工作. google protocol buffer 与 redis 结合使用 ...
- Morris莫里斯遍历
程序员代码面试指南(第2版)第3章 二叉树问题:遍历二叉树的神级方法 https://leetcode.com/articles/binary-tree-inorder-traversal/ Step ...
- Microsoft Teams 最新功能发布:协作篇
正在进行的2021年的Microsoft Ignite大会,发布了一系列跟Microsoft Teams相关的新功能,英文介绍请参考 https://techcommunity.microsoft.c ...
- Vmware虚拟机CentOS7、Ubuntu20系统设置静态IP,且主机和虚拟机系统能相互ping通。
目录 前言 一.VMware虚拟系统centos7设置静态IP 1.1 打开VMware虚拟网络配置窗口 1.2 方法1:通过DHCP服务给主机动态分配IP,同时设置centos静态IP 1.2.1 ...
- Linux下制作Windows启动U盘的工具
Linux下制作Windows启动U盘的工具 很多人说Linux下制作Windwos启动盘要用GRUB4DOS建立引导,其实不用,有专门的工具的,就像Windows下有Rufus制作Linux启动U盘 ...
- go中sync.Once源码解读
sync.Once 前言 sync.Once的作用 实现原理 总结 sync.Once 前言 本次的代码是基于go version go1.13.15 darwin/amd64 sync.Once的作 ...