From 2f7c2e973c723319431354d9b28163e66c0bb281 Mon Sep 17 00:00:00 2001 From: Lawrence37 <45837045+Lawrence37@users.noreply.github.com> Date: Sun, 4 Feb 2024 15:40:38 -0800 Subject: [PATCH] Fix rotation of images with odd number of rows (#6926) * Fix line in middle of 180 degree rotated image For images with an odd number of rows, a 180 degree rotation resulted in one row of un-rotated pixels because it was effectively rotated twice. * Replace verbose swap with std::swap --- rtengine/iimage.h | 74 ++++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 27 deletions(-) diff --git a/rtengine/iimage.h b/rtengine/iimage.h index 426b0c4c0..3e865bb2b 100644 --- a/rtengine/iimage.h +++ b/rtengine/iimage.h @@ -18,6 +18,7 @@ */ #pragma once +#include #include #include @@ -396,7 +397,7 @@ public: swap(rotatedImg); } else if (deg == 180) { - int height2 = height / 2 + (height & 1); + int height2 = height / 2; #ifdef _OPENMP // difficult to find a cutoff value where parallelization is counter productive because of processor's data cache collision... @@ -406,13 +407,22 @@ public: for (int i = 0; i < height2; i++) { for (int j = 0; j < width; j++) { - T tmp; int x = width - 1 - j; int y = height - 1 - i; - tmp = v(i, j); - v(i, j) = v(y, x); - v(y, x) = tmp; + std::swap(v(i, j), v(y, x)); + } + } + + // Middle row of odd-height images: only go half way otherwise the + // pixels will be swapped twice. + if (height & 1) { + int i = height / 2; + int width2 = width / 2; + for (int j = 0; j < width2; j++) { + int x = width - 1 - j; + + std::swap(v(i, j), v(i, x)); } } #ifdef _OPENMP @@ -828,7 +838,7 @@ public: swap(rotatedImg); } else if (deg == 180) { - int height2 = height / 2 + (height & 1); + int height2 = height / 2; #ifdef _OPENMP // difficult to find a cutoff value where parallelization is counter productive because of processor's data cache collision... @@ -838,21 +848,26 @@ public: for (int i = 0; i < height2; i++) { for (int j = 0; j < width; j++) { - T tmp; int x = width - 1 - j; int y = height - 1 - i; - tmp = r(i, j); - r(i, j) = r(y, x); - r(y, x) = tmp; + std::swap(r(i, j), r(y, x)); + std::swap(g(i, j), g(y, x)); + std::swap(b(i, j), b(y, x)); + } + } - tmp = g(i, j); - g(i, j) = g(y, x); - g(y, x) = tmp; + // Middle row of odd-height images: only go half way otherwise the + // pixels will be swapped twice. + if (height & 1) { + int i = height / 2; + int width2 = width / 2; + for (int j = 0; j < width2; j++) { + int x = width - 1 - j; - tmp = b(i, j); - b(i, j) = b(y, x); - b(y, x) = tmp; + std::swap(r(i, j), r(i, x)); + std::swap(g(i, j), g(i, x)); + std::swap(b(i, j), b(i, x)); } } #ifdef _OPENMP @@ -1481,26 +1496,31 @@ public: swap(rotatedImg); } else if (deg == 180) { - int height2 = height / 2 + (height & 1); + int height2 = height / 2; // Maybe not sufficiently optimized, but will do what it has to do for (int i = 0; i < height2; i++) { for (int j = 0; j < width; j++) { - T tmp; int x = width - 1 - j; int y = height - 1 - i; - tmp = r(i, j); - r(i, j) = r(y, x); - r(y, x) = tmp; + std::swap(r(i, j), r(y, x)); + std::swap(g(i, j), g(y, x)); + std::swap(b(i, j), b(y, x)); + } + } - tmp = g(i, j); - g(i, j) = g(y, x); - g(y, x) = tmp; + // Middle row of odd-height images: only go half way otherwise the + // pixels will be swapped twice. + if (height & 1) { + int i = height / 2; + int width2 = width / 2; + for (int j = 0; j < width2; j++) { + int x = width - 1 - j; - tmp = b(i, j); - b(i, j) = b(y, x); - b(y, x) = tmp; + std::swap(r(i, j), r(i, x)); + std::swap(g(i, j), g(i, x)); + std::swap(b(i, j), b(i, x)); } } }