QT5.14.2 指尖加油站 - 点燃Qt5图像操作的艺术火花

发布于:2024-03-28 ⋅ 阅读:(20) ⋅ 点赞:(0)

你是否也曾被图像处理的魔力所深深吸引?无论是滤镜般的模糊效果,还是缤纷绚丽的着色运算,亦或是栩栩如生的阴影映射,图像处理的艺术之美在这里尽展无余。而幸运的是,有了强大的Qt5框架,我们完全可以在自己的应用程序中,随心所欲地挥洒这些丝丝缕缕的图像魔法!


今天,就让我带你一同走进Qt5图像操作的绚丽国度,去一探这片技术的最高殿堂。我们将一一揭秘实现图像扭曲、模糊、着色、阴影和透明等高级艺术效果背后的秘密,还有大量生动的代码示例为你指路!只要跟上节奏,很快你就能在图像处理的道路上驰骋自如,遨游无际!


一、海阔波恣 - 图像扭曲效果的艺术挥洒


我们先从最基本的图像扭曲效果开始。

通过QPainterPath结合QTransform的神奇组合,我们就可以将图像扭曲成各种奇异的形状:

QImage originalImage(":/images/original.png");
QImage distortedImage(originalImage.size(), QImage::Format_ARGB32_Premultiplied);

QPainterPath path;
path.moveTo(0, 0);
path.cubicTo(100, 0, 200, 200, 300, 0);
path.cubicTo(400, 0, 500, 200, 600, 0);

QPainterPathStroker stroker;
stroker.setWidth(40);
QPainterPath strokPath = stroker.createStroke(path);

QTransform transform;
transform.setPerspectiveProjection(600, 600, 30, 30);

QPainter painter(&distortedImage);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.setTransform(transform);
painter.drawPixmap(strokPath.boundingRect(), originalImage);

这里我们首先构建了一条QPainterPath作为扭曲路径,然后使用QPainterPathStroker为路径添加了一定的宽度。

接着,我们创建了一个透视投影变换QTransform。

最后,我们在QPainter中设置了这一变换,就可以将原始图像进行扭曲绘制了。借助QPainter的绘图能力,我们完全可以把图像扭曲成任何想要的形状!


二、雾里风里 - 模糊效果带来的朦胧意境


有时模糊化的画面才是我们想要的。

Qt5中QImage自带的一些函数可以非常方便地为我们实现模糊特效:

QImage originalImage(":/images/original.png");
QImage blurredImage = originalImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);

// 简单平滑模糊
QPainter painter(&blurredImage);
painter.setRenderHint(QPainter::SmoothPixmapTransform);  
painter.drawImage(0, 0, originalImage);
blurredImage = blurredImage.convertToFormat(QImage::Format_RGB32);

// 高斯模糊
blurredImage = originalImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
blurredImage = blur(blurredImage, 10, true);

第一段代码展示了如何用QPainter实现最简单的平滑模糊效果。我们先将图像转换为预乘Alpha格式,然后再绘制到目标图像上即可。


第二段则使用了Qt内置的高斯模糊函数blur()。可以看到,通过传入合适的半径参数,就能达到更加出色的模糊效果了。这里我们还特意判断了是否只模糊Alpha通道。


除了高斯模糊,Qt还支持盒状模糊等其它模糊风格。总之,模糊肯定是图像处理中最常见的基本操作了。


三、百泉颜色 - 把色彩大师的调色盘打开


色彩往往是图像处理最令人着迷的部分。

Qt5为我们提供了多种对图像像素进行重新上色的方式,让我们可以根据需求,创造出五彩缤纷的视觉奇迹:

QImage originalImage(":/images/original.png");
QImage tintedImage = originalImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);

// 全图着色
QColor tintColor = QColorDialog::getColor(Qt::yellow, nullptr, "选择着色颜色");
QPainter painter(&tintedImage);
painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
painter.fillRect(tintedImage.rect(), tintColor);
painter.end();

// 灰度化 
QImage grayscaleImage = QImage(originalImage.size(), QImage::Format_ARGB32);
for (int y = 0; y < originalImage.height(); ++y) {
    for (int x = 0; x < originalImage.width(); ++x) {
        QRgb srcPixel = originalImage.pixel(x, y);
        int grayLevel = qGray(srcPixel);
        grayscaleImage.setPixel(x, y, qRgb(grayLevel, grayLevel, grayLevel));
    }
}

// 色相旋转
QImage hueTwistedImage = originalImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
int twistAmount = 180; // 旋转180度
for (int x = 0; x < hueTwistedImage.width(); ++x) {
    for (int y = 0; y < hueTwistedImage.height(); ++y) {
        QRgb oldRgb = hueTwistedImage.pixel(x, y);
        hueTwistedImage.setPixel(x, y, QColor::fromHsl(
            qrgb.hue() + twistAmount, qrgb.saturationF(), qrgb.lightnessF()).rgb());
    }
}

第一段代码展示了如何对整个图像进行着色。我们先获取了用户选择的着色颜色,然后通过设置QPainter的合成模式为SourceIn,绘制一个纯色的矩形,就可以让原图像的内容只保留与绘制颜色重叠的部分。


第二段则演示了如何将彩色图像转换为灰度图像。我们遍历了所有像素点,利用Qt的qGray函数计算每个像素的灰度值,并重新设置该像素的RGB值。

最后一段则展现了色相旋转的技巧。我们将图像先转为预乘Alpha格式,然后遍历所有像素点,调整每个像素的HSL色相值,再从HSL重新计算出新的RGB值。通过色相调节,就可以实现各种有趣的色彩变换了。


四、云影重重 - 渲染逼真的阴影效果


在GUI程序中,合理运用阴影效果不仅能美化界面,还可以提升控件的立体感和存在感。

幸运的是,Qt5为我们提供了多种实现阴影的工具:

QImage dropShadow(const QImage &source, qreal radius, const QColor &visibleColor, qreal exposure)
{
    QImage tmp(source.size() + QSize(radius * 2, radius * 2), QImage::Format_ARGB32_Premultiplied);
    ...
    // 自定义生成阴影图像的算法实现
    return tmp;
}

// 使用备份滤镜绘制阴影
QLabel *label = new QLabel;
label->setPixmap(QPixmap::fromImage(dropShadow(originalImage, 10, Qt::black, 0.7)));
label->setAttribute(Qt::WA_TranslucentBackground); // 开启透明背景支持
label->show();

// 使用图形效果引擎
QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect;
effect->setBlurRadius(20);
effect->setOffset(10);
effect->setColor(Qt::gray);
label->setGraphicsEffect(effect);

首先我们实现了一个dropShadow函数,用于根据传入的参数生成一张阴影图像。可以在其中自定义阴影生成算法。


接下来展示了两种使用生成的阴影图像的不同方法。一种是直接将阴影设为QLabel的背景图片,记得要开启控件透明背景支持才能正确显示阴影效果。


另一种则是使用Qt的图形效果引擎QGraphicsEffect,它提供了一系列常见的UI视觉效果,包括阴影、颜色叠加、高斯模糊等等。我们只需简单地设置QGraphicsDropShadowEffect对象的参数,就可以为控件方便地添加投影效果了。


五、隐隐仙踪 - 剖析图像变透明的神奇手段


透明度的控制也是图像处理中一个很重要的功能,Qt5为此也提供了多种灵活手段:

QImage sourceImage(":/images/original.png");

// 修改全局Alpha值
QImage globalAlphaImage = sourceImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
QPainter painter(&globalAlphaImage);
painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
painter.fillRect(globalAlphaImage.rect(), QColor(0, 0, 0, 128)); // 设置Alpha为128
painter.end();

// 修改每个像素的Alpha通道值
QImage pixelAlphaImage = sourceImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
QRgb pixel;
for (int x = 0; x < pixelAlphaImage.width(); ++x) {
    for (int y = 0; y < pixelAlphaImage.height(); ++y) {
        pixel = pixelAlphaImage.pixel(x, y);
        pixelAlphaImage.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), qAlpha(pixel)/2));
    }
}

// 使用遮罩图像控制透明度
QImage maskImage(":/images/mask.png");
QPainter maskPainter(&maskImage);
maskPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
maskPainter.drawImage(0, 0, sourceImage);
maskPainter.end();

第一段代码展示了如何修改整个图像的Alpha全局值。我们先将图像转为预乘Alpha格式,然后设置QPainter合成模式为DestinationIn,绘制一个半透明的矩形,就可以控制全图的透明度了。


第二段则介绍了如何修改每个像素点的Alpha通道值。这里我们将每个像素的Alpha值简单地除以2,也就是降低了整体不透明度。


最后一段代码演示了使用遮罩图像(mask image)来控制透明度。这里我们读取了一个Alpha通道就是想要的透明度分布的图像,将其设为QPainter的合成模式,再drawImage绘制原始图像,就可以让原图像的透明度完全遵循遮罩图像的Alpha分布了。


使用遮罩的方式非常灵活,我们不仅可以使用预设的遮罩图像,还可以动态地生成或修改遮罩图像的内容,从而实现各种瞬息万变的透明效果。

// 生成高斯模糊遮罩
QImage blurMask = sourceImage.convertToFormat(QImage::Format_ARGB32_Premultiplied); 
QPainter blurPainter(&blurMask);
blurPainter.setCompositionMode(QPainter::CompositionMode_DestinationOut);
blurPainter.drawImage(0, 0, blur(sourceImage, 10, true));
blurPainter.end();

// 结合QPainterPath做矩阵化运算
QPainterPath clipPath;
clipPath.addEllipse(100, 100, 200, 200);    
QImage shapeMask(sourceImage.size(), QImage::Format_ARGB32); 
shapeMask.fill(Qt::transparent);
QPainter shapePainter(&shapeMask);
shapePainter.setRenderHint(QPainter::Antialiasing);
shapePainter.fillPath(clipPath, Qt::white);

QPainter finalPainter(&sourceImage);    
finalPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
finalPainter.drawImage(0, 0, shapeMask);

第一段代码生成了一个高斯模糊的遮罩,可以让图像产生柔美的混合透明效果。


第二段则结合了QPainterPath,在遮罩中绘制了一个抗锯齿的椭圆形状,可以让图像按矩阵区域内外呈现不同的透明度。


可以看到,Qt5提供的多种透明度控制手段,让开发者可以在图像处理中尽情施展才华,创造出各种扣人心弦的透视效果。

六、万里一罡 - 让图像效果释放出前所未有的能量!


好了,通过上述这些生动的代码示例,相信大家已经对Qt5强大的图像处理能力有了全新的认识。无论是在2D平面图形中,还是在3D游戏场景里,亦或是在网页浏览器的渲染视图中,Qt5都为开发者们打造了一个个图像魔法的操场。


扭曲、模糊、着色、阴影、透明,这些都只是冰山一角。在Qt5的世界里,图像处理的大门才刚刚为你们打开一条缝隙。我们后续还将继续深入探索更多精彩绝伦的图像算法和特效,去开掘图像处理这片海洋的宝藏!


与此同时,Qt5强大的跨平台特性也将让你的图像处理代码在桌面电脑、手机、平板等不同硬件环境下出类拔萃。哪怕是在未来的增强现实或虚拟现实应用中,Qt5依然可以为你们挥洒无穷的魔力。


所以,紧跟着我的脚步,持续关注这一系列博文吧!我将带领大家驰骋在图像处理的绚丽疆场,去发掘更多前所未有的艺术与技术能量!让我们用指尖的码农智慧,点亮整个图像世界的灯火吧!


本文含有隐藏内容,请 开通VIP 后查看