diff options
author | CrystalP <crystalp@kodi.tv> | 2023-05-11 02:23:55 -0400 |
---|---|---|
committer | CrystalP <crystalp@kodi.tv> | 2023-05-22 10:50:43 -0400 |
commit | 0dfb62c94ebab0352b9afca68f278c9886613485 (patch) | |
tree | b1a1813c2076c93e94d2daa0a54220855a1877bb | |
parent | c827e9d4f617e34d6a728b71b7b34cd843121405 (diff) | |
download | xbmc-0dfb62c94ebab0352b9afca68f278c9886613485.tar.xz |
[thumbnails] fix rotation of pictures with non-aligned dimensions
Backport of PR#23268
-rw-r--r-- | xbmc/pictures/Picture.cpp | 92 | ||||
-rw-r--r-- | xbmc/pictures/Picture.h | 35 |
2 files changed, 87 insertions, 40 deletions
diff --git a/xbmc/pictures/Picture.cpp b/xbmc/pictures/Picture.cpp index 85124f0c8b..9c7ec1e377 100644 --- a/xbmc/pictures/Picture.cpp +++ b/xbmc/pictures/Picture.cpp @@ -257,10 +257,11 @@ bool CPicture::CacheTexture(uint8_t *pixels, uint32_t width, uint32_t height, ui if (ScaleImage(pixels, width, height, pitch, AV_PIX_FMT_BGRA, (uint8_t*)buffer, dest_width, dest_height, stride, AV_PIX_FMT_BGRA, scalingAlgorithm)) { - if (!orientation || OrientateImage(buffer, dest_width, dest_height, orientation)) + if (!orientation || + OrientateImage(buffer, dest_width, dest_height, orientation, dest_width_aligned)) { success = CreateThumbnailFromSurface((unsigned char*)buffer, dest_width, dest_height, - dest_width * 4, dest); + dest_width_aligned * 4, dest); } } delete[] buffer; @@ -312,7 +313,9 @@ bool CPicture::CreateTiledThumb(const std::vector<std::string> &files, const std texture->GetPitch(), AV_PIX_FMT_BGRA, (uint8_t*)scaled, width, height, width * 4, AV_PIX_FMT_BGRA)) { - if (!texture->GetOrientation() || OrientateImage(scaled, width, height, texture->GetOrientation())) + unsigned int stridePixels{width}; + if (!texture->GetOrientation() || + OrientateImage(scaled, width, height, texture->GetOrientation(), stridePixels)) { success = true; // Flag that we at least had one successful image processed // drop into the texture @@ -324,7 +327,7 @@ bool CPicture::CreateTiledThumb(const std::vector<std::string> &files, const std { memcpy(dest, src, width*4); dest += imageRes; - src += width; + src += stridePixels; } } } @@ -379,32 +382,36 @@ bool CPicture::ScaleImage(uint8_t* in_pixels, return false; } -bool CPicture::OrientateImage(uint32_t *&pixels, unsigned int &width, unsigned int &height, int orientation) +bool CPicture::OrientateImage(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + int orientation, + unsigned int& stridePixels) { // ideas for speeding these functions up: http://cgit.freedesktop.org/pixman/tree/pixman/pixman-fast-path.c bool out = false; switch (orientation) { case 1: - out = FlipHorizontal(pixels, width, height); + out = FlipHorizontal(pixels, width, height, stridePixels); break; case 2: - out = Rotate180CCW(pixels, width, height); + out = Rotate180CCW(pixels, width, height, stridePixels); break; case 3: - out = FlipVertical(pixels, width, height); + out = FlipVertical(pixels, width, height, stridePixels); break; case 4: - out = Transpose(pixels, width, height); + out = Transpose(pixels, width, height, stridePixels); break; case 5: - out = Rotate270CCW(pixels, width, height); + out = Rotate270CCW(pixels, width, height, stridePixels); break; case 6: - out = TransposeOffAxis(pixels, width, height); + out = TransposeOffAxis(pixels, width, height, stridePixels); break; case 7: - out = Rotate90CCW(pixels, width, height); + out = Rotate90CCW(pixels, width, height, stridePixels); break; default: CLog::Log(LOGERROR, "Unknown orientation {}", orientation); @@ -415,12 +422,13 @@ bool CPicture::OrientateImage(uint32_t *&pixels, unsigned int &width, unsigned i bool CPicture::FlipHorizontal(uint32_t*& pixels, const unsigned int& width, - const unsigned int& height) + const unsigned int& height, + const unsigned int& stridePixels) { // this can be done in-place easily enough for (unsigned int y = 0; y < height; ++y) { - uint32_t *line = pixels + y * width; + uint32_t* line = pixels + y * stridePixels; for (unsigned int x = 0; x < width / 2; ++x) std::swap(line[x], line[width - 1 - x]); } @@ -429,13 +437,14 @@ bool CPicture::FlipHorizontal(uint32_t*& pixels, bool CPicture::FlipVertical(uint32_t*& pixels, const unsigned int& width, - const unsigned int& height) + const unsigned int& height, + const unsigned int& stridePixels) { // this can be done in-place easily enough for (unsigned int y = 0; y < height / 2; ++y) { - uint32_t *line1 = pixels + y * width; - uint32_t *line2 = pixels + (height - 1 - y) * width; + uint32_t* line1 = pixels + y * stridePixels; + uint32_t* line2 = pixels + (height - 1 - y) * stridePixels; for (unsigned int x = 0; x < width; ++x) std::swap(*line1++, *line2++); } @@ -444,26 +453,30 @@ bool CPicture::FlipVertical(uint32_t*& pixels, bool CPicture::Rotate180CCW(uint32_t*& pixels, const unsigned int& width, - const unsigned int& height) + const unsigned int& height, + const unsigned int& stridePixels) { // this can be done in-place easily enough for (unsigned int y = 0; y < height / 2; ++y) { - uint32_t *line1 = pixels + y * width; - uint32_t *line2 = pixels + (height - 1 - y) * width + width - 1; + uint32_t* line1 = pixels + y * stridePixels; + uint32_t* line2 = pixels + (height - 1 - y) * stridePixels + width - 1; for (unsigned int x = 0; x < width; ++x) std::swap(*line1++, *line2--); } if (height % 2) { // height is odd, so flip the middle row as well - uint32_t *line = pixels + (height - 1)/2 * width; + uint32_t* line = pixels + (height - 1) / 2 * stridePixels; for (unsigned int x = 0; x < width / 2; ++x) std::swap(line[x], line[width - 1 - x]); } return true; } -bool CPicture::Rotate90CCW(uint32_t *&pixels, unsigned int &width, unsigned int &height) +bool CPicture::Rotate90CCW(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& stridePixels) { uint32_t *dest = new uint32_t[width * height * 4]; if (dest) @@ -476,18 +489,22 @@ bool CPicture::Rotate90CCW(uint32_t *&pixels, unsigned int &width, unsigned int for (unsigned int x = 0; x < d_width; x++) { *dst++ = *src; - src += width; + src += stridePixels; } } delete[] pixels; pixels = dest; std::swap(width, height); + stridePixels = width; return true; } return false; } -bool CPicture::Rotate270CCW(uint32_t *&pixels, unsigned int &width, unsigned int &height) +bool CPicture::Rotate270CCW(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& stridePixels) { uint32_t *dest = new uint32_t[width * height * 4]; if (!dest) @@ -496,22 +513,27 @@ bool CPicture::Rotate270CCW(uint32_t *&pixels, unsigned int &width, unsigned int unsigned int d_height = width, d_width = height; for (unsigned int y = 0; y < d_height; y++) { - const uint32_t *src = pixels + width * (d_width - 1) + y; // y-th col from left, starting at bottom - uint32_t *dst = dest + d_width * y; // y-th row from top, starting at left + const uint32_t* src = + pixels + stridePixels * (d_width - 1) + y; // y-th col from left, starting at bottom + uint32_t* dst = dest + d_width * y; // y-th row from top, starting at left for (unsigned int x = 0; x < d_width; x++) { *dst++ = *src; - src -= width; + src -= stridePixels; } } delete[] pixels; pixels = dest; std::swap(width, height); + stridePixels = width; return true; } -bool CPicture::Transpose(uint32_t *&pixels, unsigned int &width, unsigned int &height) +bool CPicture::Transpose(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& stridePixels) { uint32_t *dest = new uint32_t[width * height * 4]; if (!dest) @@ -525,17 +547,21 @@ bool CPicture::Transpose(uint32_t *&pixels, unsigned int &width, unsigned int &h for (unsigned int x = 0; x < d_width; x++) { *dst++ = *src; - src += width; + src += stridePixels; } } delete[] pixels; pixels = dest; std::swap(width, height); + stridePixels = width; return true; } -bool CPicture::TransposeOffAxis(uint32_t *&pixels, unsigned int &width, unsigned int &height) +bool CPicture::TransposeOffAxis(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& stridePixels) { uint32_t *dest = new uint32_t[width * height * 4]; if (!dest) @@ -544,17 +570,19 @@ bool CPicture::TransposeOffAxis(uint32_t *&pixels, unsigned int &width, unsigned unsigned int d_height = width, d_width = height; for (unsigned int y = 0; y < d_height; y++) { - const uint32_t *src = pixels + width * (d_width - 1) + (d_height - 1 - y); // y-th col from right, starting at bottom + const uint32_t* src = pixels + stridePixels * (d_width - 1) + + (d_height - 1 - y); // y-th col from right, starting at bottom uint32_t *dst = dest + d_width * y; // y-th row, starting at left for (unsigned int x = 0; x < d_width; x++) { *dst++ = *src; - src -= width; + src -= stridePixels; } } delete[] pixels; pixels = dest; std::swap(width, height); + stridePixels = width; return true; } diff --git a/xbmc/pictures/Picture.h b/xbmc/pictures/Picture.h index 2d469d795d..33cb9c7228 100644 --- a/xbmc/pictures/Picture.h +++ b/xbmc/pictures/Picture.h @@ -77,21 +77,40 @@ public: CPictureScalingAlgorithm::Algorithm scalingAlgorithm = CPictureScalingAlgorithm::NoAlgorithm); private: - static bool OrientateImage(uint32_t *&pixels, unsigned int &width, unsigned int &height, int orientation); + static bool OrientateImage(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + int orientation, + unsigned int& stridePixels); static bool FlipHorizontal(uint32_t*& pixels, const unsigned int& width, - const unsigned int& height); + const unsigned int& height, + const unsigned int& stridePixels); static bool FlipVertical(uint32_t*& pixels, const unsigned int& width, - const unsigned int& height); - static bool Rotate90CCW(uint32_t *&pixels, unsigned int &width, unsigned int &height); - static bool Rotate270CCW(uint32_t *&pixels, unsigned int &width, unsigned int &height); + const unsigned int& height, + const unsigned int& stridePixels); + static bool Rotate90CCW(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& stridePixels); + static bool Rotate270CCW(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& stridePixels); static bool Rotate180CCW(uint32_t*& pixels, const unsigned int& width, - const unsigned int& height); - static bool Transpose(uint32_t *&pixels, unsigned int &width, unsigned int &height); - static bool TransposeOffAxis(uint32_t *&pixels, unsigned int &width, unsigned int &height); + const unsigned int& height, + const unsigned int& stridePixels); + static bool Transpose(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& width_aligned); + static bool TransposeOffAxis(uint32_t*& pixels, + unsigned int& width, + unsigned int& height, + unsigned int& stridePixels); }; //this class calls CreateThumbnailFromSurface in a CJob, so a png file can be written without halting the render thread |