Михаил Сермяжко
14 февраля 2022 г. 20:24

Мерцание при обновлении картинки в QML

QML, Android, Qt

Добрый день.
Получаю от сервера 10-30 картинок в секунду, вот так преобразовываю

  1. QUrl AppCore::imageToUrl(const QImage &image)
  2. {
  3. QByteArray byteArray;
  4. QBuffer buffer(&byteArray);
  5. buffer.open(QIODevice::WriteOnly);
  6. image.save(&buffer, "png");
  7. QString base64 = QString::fromUtf8(byteArray.toBase64());
  8. return QString("data:image/png;base64,") + base64;
  9. }

и отправляю QUrl в sourse Image. На десктопе все более менее работает, только при обновлении других виджетов может получится мерцание. На андроите получается постоянное мерцание (исчезновение карти, отображение фона, последующее отображение картинки). Скажите пожалуйста, в чем может быть дело и как это можно исправить? Может быть можно перевести картинки в видео и так их отображать в QML?

2

Вам это нравится? Поделитесь в социальных сетях!

9
Evgenii Legotckoi
  • 14 февраля 2022 г. 20:33
  • (ред.)

Добрый день,
Это у вас типо видеострима работает? А покажите кусок кода, где это функция применяется?
Может дело в том, что у вас пустует source пока конвертируется изображение? Я бы в этом случае испускал сигнал с QUrl вместо прямого использования метода. В таком случае можно будет приконнектиться к AppCore и реагировать уже на готовое изображение и только тогда менять source изображения.

    Михаил Сермяжко
    • 14 февраля 2022 г. 20:52

    Я получаю ответ от сервера с картинкой в виде массива байт и так обрабатываю через Q_PROPERTY

    1. setProperty("iRImageUrl", "data:image/png;base64," + doc.object()["data"].toString());

    Так же я пробовал испускать сигнал и передавать полученное значение в QML в source, но мерцание при обновлении сохранилось

    1. emit currentIRImageChanged("data:image/png;base64," + doc.object()["data"].toString());
      Evgenii Legotckoi
      • 14 февраля 2022 г. 21:01
      • (ред.)

      Я думаю, что вашу проблему мог бы решить QQuickImageProvider

      Вполне возможно что все эти мерцания из-за того, что изображение обновляется совместно со всем интерфейсом, а если это сделать через QQuickImageProvider, то там это будет работать более асинхронно, что может решить проблему.

      Тем более, что здесь говорится как раз про потоковую передачу изображений в Image объект в QML

      The QQuickImageProvider class provides an interface for supporting pixmaps and threaded image requests in QML

        Михаил Сермяжко
        • 15 февраля 2022 г. 15:08
        • (ред.)

        Попробовал. Не помогло.
        Класс сделал так

        1. class ImageProvider : public QQuickImageProvider
        2. {
        3. public:
        4. ImageProvider() : QQuickImageProvider(QQuickImageProvider::Pixmap)
        5. {
        6. }
        7.  
        8. QPixmap m_pixmap = QPixmap("/home/owner/Загрузки/image_2022-02-04_15-52-48.png");
        9.  
        10. QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override
        11. {
        12. return m_pixmap;
        13. }
        14. };

        В мэйне записал так

        1. engine.addImageProvider(QLatin1String("imageProviderIRImage"), appCore->m_imageProviderIRImage);

        В QML задал источник так

        1. source: "image://imageProviderIRImage"

        Но при такой реализации отображается только заданная в классе картинка, оно не обновляется при изменении m_pixmap
        m_pixmap меняю так

        1. QByteArray arr = QByteArray::fromBase64(doc.object()["data"].toString().toLatin1());
        2. m_imageProviderIRImage->m_pixmap.loadFromData(arr);

        функция requestPixmap вызфвается только один раз

          Evgenii Legotckoi
          • 15 февраля 2022 г. 15:47

          Думаю, тут посложнее код должен быть, я бы попробовал совместить код из imageToUrl, чтобы заменять картинку в провайдере. Пока у меня только такие мысли есть.

            Михаил Сермяжко
            • 15 февраля 2022 г. 15:58

            Дело в том,что в провайдере и так меняется картинка, просто похоже это дергается только один раз при вызове в мэйне.

              Evgenii Legotckoi
              • 15 февраля 2022 г. 16:49

              Эммм, может тогда ещё поиграть с настройками самого Image? В документации сказано, что есть следующие свойства:

              • asynchronous - асинхронная загрузка, которая по умолчанию false, кроме изображений из сети.
              • cache - кэширование изображений, которое по умолчанию true, может при изменении изображения в источнике, из-за кеширование не срабатывает?

              Я уже не знаю, сейчас разве что только пальцем в небе попаду.

                Михаил Сермяжко
                • 15 февраля 2022 г. 16:58
                • Ответ был помечен как решение.

                Я сделал сигнал обновления картинки и менял потом source картинки так, в таком случае работает без мерцания

                1. imageIrImage.source = "image://imageProviderIRImage/ir"
                2. imageIrImage.source = "image://imageProviderIRImage"
                  Evgenii Legotckoi
                  • 15 февраля 2022 г. 17:03

                  Получается, что доколупали.
                  Решение - QQuickImageProvider + сигнал на обновление. Тоже вариант.

                    Комментарии

                    Только авторизованные пользователи могут публиковать комментарии.
                    Пожалуйста, авторизуйтесь или зарегистрируйтесь