LINUX.ORG.RU

C++, Qt, бесконечная прокручивающаяся страница с графическими данными.


0

2

У меня есть картинка с научными графическими данными 1024x100500 пикселей. То есть, ширина обычная, длина потенциально бесконечная.

Юзер прокручивает эту картинку как веб-страницу в моём GUI. Я оперирую картинкой как таблицей блоков 1024x128 и показываю нужный участок картинки по принципу гугл-мэпс: юзер прокрутил до определённого региона, я вытаскиваю опр. поеледовательность блоков и показываю. Для оптимизации, в памяти храню максимум N блоков, переиспользуя их под новые участки.

Для хранения блоков используется QPixmap, ибо это обёртка над хранящимися данными в памяти иксов/или виндового графического ядра, в удобном для ядра и видеокарты формате. То есть, быстрее вывести в окно массив пикселей будет тяжело.

Теперь я хочу режим, в котором свежие поступающие данные дорисовываются к картинке снизу (новыми линиями) и юзер видит появление этих линий не дожидаясь формирования целых блоков высотой 128. Для красоты вопроса допустим, что частота появления новых линий - 30fps, а если больше - пускай сразу по нескольку дорисовываются.

Рисовать в Qt принято в QImage, который хранит данные в памяти процесса в удобном для изменения виде. Но показывать этот QImage - гораздо более тормозная процедура, чем показывать QPixmap.

Можно: 1) Показывать уже готовые блоки как QPixmap, а новые линии рисовать на временном QImage и его же показывать. То есть, показывать N QPixmap-ов и один QImage. На современном железе это наверное даже не будет тормозить даже на 30fps. Не замерял.

2) Создать 128 временных QPixmap и использовать очередной из них под новую линию, а при использовании их всех - сбрасывать в новый большой QPixmap и продолжать рисование на временных. Недостаток: при высоте экрана 1200px, я покажу всю картинку всего за 8 вызовов «покажи большой QPixmap», а последний дорисовывающийся блок будет требовать 127 вызовов «покажи мелкий QPixmap». Незнаю даже что хуже, этот или первый способ.

Ну, вопрос: чё делать-то? )

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

unC0Rr ★★★★★
()

А разве BitBlt отменили совсем?

1. Завести в памяти 2 пиксмапа размером в содержимое окна. Рисовать в них поступающие данные по принципу пинг-понга - один заполнили - рисуем в другой, другой заполнился - рисуем в первый.

2. Для скролла использовать BitBlt экрана на самое себя со сдвигом

3. При отрисовке «нижнего» или «верхнего» куска экрана «оголившегося» при скролле просто делать BitBlt готовой части из «текущего» пиксмапа в который заносятся новые данные целиком, а не по одной линии.

В итоге скроллинг обойдётся в 2 BitBlt. Один - сдвиг содержимого окна, второй - копирование недостающей части из пиксмапа. Перерисовка окна - тоже максимум 2 BitBlt, только в обоих случаях из пиксмапов.

Ну и разумеется рисовать данные прямиком в пиксмапы, а не через ж.

PROFIT.

Stanson ★★★★★
()
Ответ на: комментарий от Stanson

Извиняюсь за тупость: не понял, при чём тут BitBlt. Нельзя ли пояснить?

Скроллинг не всегда равномерный, иногда юзер дёргает скроллбаром как хочет туда-сюда, мне тут какие-то хитрости с копированием экрана самого на себя не нужны уже.

Ну и разумеется рисовать данные прямиком в пиксмапы, а не через ж.

Рисовать сразу в QPixmap очень дорого, рисовать дёшево - в QImage, а потом его за один вызов конвертировать в QPixmap.

Вопрос не в скроллинге, а в дорисовывании новых линий в риалтайм.

kiverattes ★☆
() автор топика
Последнее исправление: kiverattes (всего исправлений: 3)
Ответ на: комментарий от KblCb

Какими-то простыми FFT-классами, найденными на просторах инета. Что значит «pixmap так pixmap»? :) Плюс подобранная на коленке процедура загона диапазона получаемых результатов в цветовое пространство 0...255, грубо говоря.

kiverattes ★☆
() автор топика
Ответ на: комментарий от pathfinder

QImage хранит данные в памяти приложения в формате, заточенном под прямой доступ к цветам пикселей - типа массива «RGBARGBA...». QPixmap держит данные в памяти иксов в формате, удобном для записи в видеокарту - по-сути QPixmap - просто ссылка на выделенный иксовый пиксельный буфер. Соответственно, чтобы модифицировать QPixmap - надо гонять туда-сюда данные и переводить между форматами туда-сюда. Поэтому, обычно рисуют в QImage, а потом целиком конвертят в QPixmap.

kiverattes ★☆
() автор топика
Ответ на: комментарий от kiverattes

не понял, при чём тут BitBlt. Нельзя ли пояснить?

BitBlt - это операция которая, как правило, аппаратно ускорена и выполняется видеокартой а не процессором. Копирование QPixmap (как и аналогичные вещи в других тулкитах) сделано через BitBlt.

Скроллинг не всегда равномерный, иногда юзер дёргает скроллбаром как хочет туда-сюда, мне тут какие-то хитрости с копированием экрана самого на себя не нужны уже.

Как раз никаких хитростей. В произвольный момент приезжает событие «юзер прокрутил экран на дцать пикселей». Сдвигаем экран на дцать пикселей + копируем дцать пикселей из пиксмапа. То, что это будет происходить часто и быстро если юзер дрочит колёсико - не имеет значения. Событие будет одно и то же с разным параметром сдвига.

Рисовать сразу в QPixmap очень дорого

Дешевле чем рисование в пиксмап нет ничего. Достаточно узнать адрес буфера пиксмапа и организацию бит на пиксель. Операции с памятью всегда дешевле чем вызовы функций тулкита.

Вопрос не в скроллинге, а в дорисовывании новых линий в риалтайм.

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

Stanson ★★★★★
()
Ответ на: комментарий от Stanson

Дешевле чем рисование в пиксмап нет ничего.

Есть - операция рисования в QImage. Тоже прямая работа с памятью, без вызовов, причём с такой памятью, где данные лучшим образом оптимизированы под работу с пикселями, чем данные в иксовом буфере. Плюс, городить код под прямую манипуляцию с иксовым буфером и под прямую манипуляцию с виндовым буфером, да ещё в разных видеорежимах - проще застрелиться. Не стоит получаемого ускорения совсем такая затрата трудов.

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

Вопрос не про кручение колеса. Этот вопрос давно решён. Вопрос про получение новых данных и выводе их как можно скорее, не дожидаясь формирования целых блоков 1024x128.

kiverattes ★☆
() автор топика
Последнее исправление: kiverattes (всего исправлений: 1)
Ответ на: комментарий от kiverattes

городить код под прямую манипуляцию с иксовым буфером и под прямую манипуляцию с виндовым буфером, да ещё в разных видеорежимах - проще застрелиться

Ничего сложного, вообще-то. Спросил формат - рисуешь. Хотя и несколько геморройнее чем QImage, да. Зато не нужно будет блоков всяких.

Вопрос не про кручение колеса. Этот вопрос давно решён. Вопрос про получение новых данных и выводе их как можно скорее, не дожидаясь формирования целых блоков 1024x128.

Рисованием в пиксмап устраняется сама эта проблема в корне. Вообще в принципе не нужно дожидаться «формирования целых блоков 1024x128».

Stanson ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.