diff options
author | Miguel Borges de Freitas <92enen@gmail.com> | 2023-06-24 11:43:20 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-24 11:43:20 +0100 |
commit | a0bcc4281cb9996f088fe7b93a49396b7fce8753 (patch) | |
tree | a26af5c8f9a2931549a7492475fcecff695fd1db | |
parent | 9a44d078a3063fa415b91727ae3f573bf17bbf20 (diff) | |
parent | 0dfb62c94ebab0352b9afca68f278c9886613485 (diff) | |
download | xbmc-a0bcc4281cb9996f088fe7b93a49396b7fce8753.tar.xz |
Merge pull request #23319 from CrystalP/bp-fix-rotated-thumbnails
Fix Thumbnails of Rotated Pictures
-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 b9999456da..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, - stride, 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 ee5a270d86..192982aa1a 100644 --- a/xbmc/pictures/Picture.h +++ b/xbmc/pictures/Picture.h @@ -79,21 +79,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 |