aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCrystalP <crystalp@kodi.tv>2023-05-11 02:23:55 -0400
committerCrystalP <crystalp@kodi.tv>2023-05-22 10:50:43 -0400
commit0dfb62c94ebab0352b9afca68f278c9886613485 (patch)
treeb1a1813c2076c93e94d2daa0a54220855a1877bb
parentc827e9d4f617e34d6a728b71b7b34cd843121405 (diff)
downloadxbmc-0dfb62c94ebab0352b9afca68f278c9886613485.tar.xz
[thumbnails] fix rotation of pictures with non-aligned dimensions
Backport of PR#23268
-rw-r--r--xbmc/pictures/Picture.cpp92
-rw-r--r--xbmc/pictures/Picture.h35
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