Explicitly release GIL while loading QImage in thumbnail renderer thread

This commit is contained in:
Kovid Goyal 2026-01-17 11:16:44 +05:30
parent 22916f8f22
commit 4eb9d9eca2
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 10 additions and 8 deletions

View File

@ -21,6 +21,7 @@ from qt.core import QBuffer, QByteArray, QColor, QImage, QImageWriter, QIODevice
from calibre.db.utils import ThumbnailCache as TC
from calibre.utils import join_with_timeout
from calibre.utils.img import resize_to_fit
from calibre_extensions.imageops import load_from_data_without_gil
class ThumbnailCache(TC):
@ -129,7 +130,7 @@ class Thumbnailer:
if not cover_as_bytes:
return self.thumbnail_class(), b''
cover: QImage = self.thumbnail_class()
if not cover.loadFromData(cover_as_bytes):
if not load_from_data_without_gil(cover, cover_as_bytes):
return cover, b''
cover = self.resize_to_fit(cover, width, height)
serialized = self.serialize(cover)

View File

@ -639,7 +639,6 @@ void overlay(const QImage &image, QImage &canvas, unsigned int left, unsigned in
} // }}}
QColor dominant_color(const QImage &image) { // {{{
ScopedGILRelease PyGILRelease;
if (image.isNull()) return QColor();
QImage img;
// Resize the image to a thumbnail for improved performance
@ -1005,3 +1004,7 @@ QImage texture_image(const QImage &image, const QImage &texturei) { // {{{
}
return canvas;
} // }}}
bool load_from_data_without_gil(QImage &image, const char *data, size_t len) { // {{{
return image.loadFromData((const uchar*)data, len, NULL);
} // }}}

View File

@ -25,6 +25,7 @@ QImage set_opacity(const QImage &image, double alpha);
QImage texture_image(const QImage &image, const QImage &texturei);
QImage ordered_dither(const QImage &image);
QColor dominant_color(const QImage &image);
bool load_from_data_without_gil(QImage &image, const char *data, size_t len);
class ScopedGILRelease {
public:

View File

@ -18,6 +18,8 @@
} catch (...) { PyErr_SetString(PyExc_RuntimeError, "unknown error"); return NULL;}
%End
bool load_from_data_without_gil(QImage &image, const char *data /Array/, size_t len /ArraySize/) /ReleaseGIL/;
QImage* remove_borders(const QImage &image, double fuzz);
%MethodCode
IMAGEOPS_PREFIX
@ -74,12 +76,7 @@ QImage oil_paint(const QImage &image, const float radius=-1, const bool high_qua
IMAGEOPS_SUFFIX
%End
QColor dominant_color(const QImage &image);
%MethodCode
IMAGEOPS_PREFIX
sipRes = new QColor(dominant_color(*a0));
IMAGEOPS_SUFFIX
%End
QColor dominant_color(const QImage &image) /ReleaseGIL/;
QImage quantize(const QImage &image, unsigned int maximum_colors, bool dither, const QList<QRgb> &palette);
%MethodCode