我已经知道如何垂直或水平翻转图像。我有以下水平执行的代码。就像我在这里使用Qt一样,这里的图像数据存储在QImage中。
QImage image(imageFileName);
QImage newImage(image);
if(image.depth() > 8)
{
for (int idx_Y = 0; idx_Y < image.height(); idx_Y++)
{
for (int idx_X = 0; idx_X < image.width(); idx_X++)
{
QRgb rgb = image.pixel(image.width() - 1 - idx_X, idx_Y);
newImage.setPixel(idx_X, idx_Y, rgb);
}
}
}
我敢肯定有更快的方法可以完成它。但是,我不想在堆上分配任何内存。您能告诉我还有什么其他更快的算法吗?
谢谢。
答案 0 :(得分:2)
详细介绍@Spektres hint
2嵌套的for循环不是问题... setPixel和pixel函数通常在大多数gfx API上都是爬行式的。相反,使用直接像素访问通常可以将速度提高约1000倍或更多...
这看起来像:
QImage image(imageFileName);
QImage newImage(image);
if (image.depth() >= 8) {
const int bytesPerPixel = image.depth() / 8;
for (int y = 0; y < image.height(); ++y) {
char *dataSrc = image.bits() + y * image.bytesPerLine();
char *dataDst = newImage.bits() + y * newImage.bytesPerLine()
+ (newImage.width() - 1) * bytesPerPixel;
for (int i = image.width(); i--;
dataSrc += bytesPerPixel, dataDst -= bytesPerPixel) {
for (int i = 0; i < bytesPerPixel; ++i) dataDst[i] = dataSrc[i];
}
}
}
请注意,我将image.depth() > 8
更改为image.depth() >= 8
。 (我认为没有理由排除QImage::Format_Grayscale8
。)
经过稍微修改的版本,用于就地镜像QImage newImage
(考虑到它已经被复制):
QImage image(imageFileName);
QImage newImage(image);
if (newImage.depth() >= 8) {
const int bytesPerPixel = newImage.depth() / 8;
for (int y = 0; y < image.height(); ++y) {
char *dataL = newImage.bits() + y * newImage.bytesPerLine();
char *dataR = dataL + (newImage.width() - 1) * bytesPerPixel;
for (; dataL < dataR; dataL += bytesPerPixel, dataR -= bytesPerPixel) {
for (int i = 0; i < bytesPerPixel; ++i) std::swap(dataL[i], dataR[i]);
}
}
}
关于QImage
和qRgb()
,您可能还会注意到Qt支持QImage
,每个分量16位(自Qt 5.12开始)。
我在这个中摆弄了一点
SO: Set pixel value of 16 bit grayscale QImage
这也可能很有趣。