Is there any libraries to save big images and not freeze pyqt gui?

hi, I have a gui in pyqt and have a worker thread that does calculations and time consuming operations, I have to save a big image at the end of run when save button is clicked so I connected save button to a slot in worker thread but when I click save it freezes gui and it becomes not responding until cv2.imwrite finishes saving file, I wanted to know if there is any library that can save big images(50000*50000) and not freeze gui during save?

Hello @SinPool,

To avoid freezing your PyQt GUI while saving large images, you can use QThread to handle the saving process in the background. This will keep your GUI responsive;

Here’s a simple example;

from PyQt5.QtCore import QThread, pyqtSignal
import cv2

class ImageSaver(QThread):
    finished = pyqtSignal()

    def __init__(self, image, file_path):
        super().__init__()
        self.image = image
        self.file_path = file_path

    def run(self):
        cv2.imwrite(self.file_path, self.image)
        self.finished.emit()

When the save button is clicked, start this thread to handle the image saving. This way, your GUI won’t freeze.

Hope this helps… :blush:

1 Like

Hey @SinPool since you already have a thread for the work, I suspect the hanging issue is happening because you’re calling the save method from outside the thread. If you call a method on a thread object from the main GUI thread, that method will run in the GUI thread. In order to handle the save on the non-GUI thread you need to initiate the call from there.

As @gabrielparker says you can pass the resulting image & filename to an additional worker to handle the save.

Alternatively, you can pause your initial thread and have it wait for the filename to be passed in via the external method. Something like:

from PyQt5.QtCore import QThread, pyqtSignal
import cv2
import time

class ImageProcessor(QThread):
    finished = pyqtSignal()

    def __init__(self:
        super().__init__()
        self.image = image
        self.file_path = None

    def run(self):
        # Do some image processing
        while self.file_path is None:
                 time.sleep(1)

        cv2.imwrite(self.file_path, self.image)
        self.finished.emit()

    def set_save_path(self, path):
          self.file_path = path

Calling set_save_path from outside the thread will set the path & allow the main code in the run() method to proceed.

I’d usually suggest spinning up a different worker for this task, but thought this might help illustrate the issue better for you.

Try by Modifying your existing save button connection.

self.save_button.clicked.connect(self.on_save_button_clicked)

I hope this will help.

Thanks