Bug 450503 - ThumbCreator: QImage with bytesPerLine > width*4 is rendered incorrectly
Summary: ThumbCreator: QImage with bytesPerLine > width*4 is rendered incorrectly
Status: REPORTED
Alias: None
Product: kio-extras
Classification: Frameworks and Libraries
Component: Thumbnails and previews (show other bugs)
Version: 21.12.2
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: Plasma Bugs List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-02-18 07:16 UTC by David Korth
Modified: 2022-02-18 07:16 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description David Korth 2022-02-18 07:16:19 UTC
I have a multi-platform shell extension called "rom-properties". It uses some custom memory management for performance; namely, it uses 16-byte aligned memory buffers for QImage to allow usage of SSE2 and SSSE3-optimized algorithms.

I recently encountered an image from the Khronox KTX test suite, hi_mark_sq.ktx, that's 145x130 24-bit color. When decoded to 32-bit color, it's 580 bytes per row if not using custom row alignment; however, with 16-byte alignment, it's 592 bytes per row. QImage handles this perfectly fine, but once I hand it off to KIO in my ThumbCreator::create() function, it gets distorted. I narrowed this down to the SHM code in kio/src/widgets/previewjob.cpp and kio-extras/thumbnail/thumbnail.cpp, which does not account for bytesPerLine differing from width * bytes per pixel.

This is likely an edge case, but at the very least, some documentation should be added to ThumbCreator to indicate that this would be distorted.

I did add a workaround to my own code to create a copy of the QImage without the extra row bytes. kio-extras has a similar workaround for paletted images by converting it to ARGB32, so maybe this workaround can be added here.

https://invent.kde.org/network/kio-extras/-/blob/master/thumbnail/thumbnail.cpp#L318

Something like:

if (img.format() != QImage::Format_ARGB32) { // KIO::PreviewJob and this code below completely ignores colortable :-/,
    img = img.convertToFormat(QImage::Format_ARGB32); //  so make sure there is none
} else if (img.width() * 4 != img.bytesPerLine()) {
    img = img.copy();
}