Я не хочу испортить чей-либо день, но если вы не хотите идти по пути IPP (см. Photo_tom) или использовать оптимизированную библиотеку, вы можете получить более высокую производительность из следующего (модифицируя ответ Андреаса):
uchar *iplImagePtr = (uchar *) iplImage->imageData;
uchar buf;
size_t limit = height * width;
for (size_t y = 0; y < limit; ++y) {
std::swap(iplImagePtr[y * 3], iplImagePtr[y * 3 + 2]);
}
Теперь подождите, ребята, я слышу, как вы кричите "но все эти дополнительные умножения и добавления!" Дело в том, что эту форму цикла проще оптимизировать компилятору намного , особенно если он становится достаточно умным для многопоточности такого рода алгоритма, потому что каждый проход цикла не зависит от до или после. В другой форме значение iplImagePtr
зависело от значения в предыдущем проходе. В этой форме это константа по всему циклу; изменяется только y
, и это в очень, очень распространенной конструкции цикла «считать от 0 до N-1», поэтому оптимизатору легче переварить.
Или, может быть, это не имеет значения в наши дни, потому что оптимизаторы безумно умны (не так ли?). Интересно, что бы сказал тест?
P.S. Если вы действительно сравните это, я также хотел бы увидеть, насколько хорошо работает следующее:
uchar *iplImagePtr = (uchar *) iplImage->imageData;
uchar buf;
size_t limit = height * width;
for (size_t y = 0; y < limit; ++y) {
uchar *pixel = iplImagePtr + y * 3;
std::swap(pix[0], pix[2]);
}
Опять же, pixel
определен в цикле, чтобы ограничить его область действия и не дать оптимизатору думать, что существует циклическая зависимость. Если компилятор увеличивает и уменьшает указатель стека каждый раз в цикле для «создания» и «уничтожения» pixel
, что ж, это глупо, и я извинюсь за трату вашего времени.