static QImage addGrassStyle(const QImage& source, int minX, int minY, int maxX, int maxY, int radius = 10){ auto bottomRight = source.rect().bottomRight();
if (minX < 0) { minX = 0; } if (minY < 0) { minY = 0; } if (maxX > bottomRight.rx()) { maxX = bottomRight.rx(); } if (maxY > bottomRight.ry()) { maxY = bottomRight.ry(); }
QImage result = source.copy(); for (int x = minX; x <= maxX; x++) { for (int y = minY; y <= maxY; y++) { auto randNum = rand() % (radius + 1); auto nearX = x + randNum < bottomRight.rx() ? x + randNum : x - randNum; auto nearY = y + randNum < bottomRight.ry() ? y + randNum : y - randNum; result.setPixel(x, y, source.pixel(nearX, nearY)); } }
static QImage addGaussianBlur(const QImage& source, int minX, int minY, int maxX, int maxY){ constexprint kernel[5][5] = {{1, 4 , 6 , 4 , 1}, {4, 16, 24, 16, 4}, {6, 24, 36, 24, 6}, {4, 16, 24, 16, 4}, {1, 4 , 6 , 4 , 1}}; // 高斯核 constexprint diameter = sizeof(kernel[0]) / sizeof(int); constexprint radius = diameter / 2; int totalWeight = 0; for (int y = 0; y < diameter; y++) { for (int x = 0; x < diameter; x++) { totalWeight += kernel[y][x]; } }
// 边界处理, 只计算邻域可覆盖完整高斯核的区域 if (minX < radius) { minX = radius; } if (minY < radius) { minY = radius; } int gapX = source.width() - maxX; int gapY = source.height() - maxY; if (gapX < radius) { maxX -= radius; } if (gapY < radius) { maxY -= radius; }
QImage result = source.copy(); for (int x = minX; x < maxX; x++) { for (int y = minY; y < maxY; y++) { int r = 0; int g = 0; int b = 0; for (int nearX = -radius; nearX <= radius; nearX++) { for (int nearY = -radius; nearY <= radius; nearY++) { QRgb color = source.pixel(x + nearX, y + nearY); r += qRed(color) * kernel[radius + nearX][radius + nearY]; g += qGreen(color) * kernel[radius + nearX][radius + nearY]; b += qBlue(color) * kernel[radius + nearX][radius + nearY]; } } result.setPixel(x, y, qRgb(r / totalWeight, g / totalWeight, b / totalWeight)); // 记得要除以总权重 } } return result; }
static QImage addGaussianBlurEx(const QImage& source, int minX, int minY, int maxX, int maxY){ constexprint kernel[5] = {1, 4 , 6 , 4 , 1}; // 一维空间高斯核 constexprint radius = sizeof(kernel) / sizeof(int) / 2; int totalWeight = 0; for (int weight : kernel) { totalWeight += weight; } totalWeight *= 2; // 实际上有 X/Y 轴两个方向上的高斯核, 因此总权重是两倍
if (minX < radius) { minX = radius; } if (minY < radius) { minY = radius; } int gapX = source.width() - maxX; int gapY = source.height() - maxY; if (gapX < radius) { maxX -= radius; } if (gapY < radius) { maxY -= radius; }
QImage result = source.copy();
for (int x = minX; x < maxX; x++) { for (int y = minY; y < maxY; y++) { int r = 0; int g = 0; int b = 0; for (int nearPos = -radius; nearPos <= radius; nearPos++) { QRgb colorX = source.pixel(x + nearPos, y); // X 轴方向 r += qRed(colorX) * kernel[radius + nearPos]; g += qGreen(colorX) * kernel[radius + nearPos]; b += qBlue(colorX) * kernel[radius + nearPos];
QRgb colorY = source.pixel(x, y + nearPos); // Y 轴方向 r += qRed(colorY) * kernel[radius + nearPos]; g += qGreen(colorY) * kernel[radius + nearPos]; b += qBlue(colorY) * kernel[radius + nearPos]; } result.setPixel(x, y, qRgb((r / totalWeight), (g / totalWeight), (b / totalWeight))); } }