如何把一张大图马赛克化(如下图所示)
最直观的方案就是:
-
把大图拆分成N个小矩形,每个小矩形就是一个马赛克格子;
-
得到每个小矩形内的所有像素的颜色,然后计算这些颜色的平均值。
-
用颜色平均值填充这些小矩形;
这个方案又复杂又慢。下面是新方案的实现步骤:
-
使用平滑算法把大图像缩小成一个小图像,小图像上每一个像素就是一个马赛克格子的填充像素;也就是说小图像上每个像素与大图像上的马赛克格子一一对应;
-
用小图像上的像素颜色填充大图像上的马赛克格子;
好,现在来看代码:
int mosaicRectSize{ 18 };
QImage imgTemp = imgScreen.scaled(
imgScreen.width() / mosaicRectSize,
imgScreen.height() / mosaicRectSize,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
auto dpr = windowHandle()->devicePixelRatio();
auto smallSize = mosaicRectSize / dpr;
for (uint x = 0; x < imgTemp.width(); x++)
{
for (uint y = 0; y < imgTemp.height(); y++)
{
auto c = imgTemp.pixelColor(x, y);
painter.setBrush(c);
painter.setPen(Qt::NoPen);
QRect mRect(x * smallSize, y * smallSize,
smallSize, smallSize);
painter.drawRect(mRect);
}
}
这段代码中有以下几点值得注意:
-
mosaicRectSize是马赛克格子的大小。
-
imgScreen是大图像。
-
imgTemp是大图像缩小后得到的小图像。
-
使用Qt::SmoothTransformation缩小大图像,Qt框架会帮我们计算好小图像上每个像素的颜色(也就是说,为每个马赛克格子取平均颜色的工作交给了Qt框架)。
-
绘制马赛克格子时考虑了图像的设备像素比,确保大图像所有区域都被马赛克化。
如你所见,方案足够简单,在我的电脑上(i9,48G)处理2560*1440的图像,大概30ms左右,执行效率也不错!(马赛克格子越大,效率越高)。