Название: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Март 08, 2009, 17:22 Общая задача: Есть графический файл *.bmp с разрешением примерно (40 000 х 30 000 точек), ясно что в ОЗУ не запихнешь, его нужно отобразить с возможностью перемещения БЕЗ каких либо тормозов.
Для того, чтобы отобразить такое большое изображение ясно что надо читать его с диска, для этого создаю свою структуру данных (т.е. свой файл, с которым буду работать). В эти подробности вникать не стоит, важно то, что могу из него прочитать заданный квадрат, разрешением (допустим) 500х500 пикселей в матрицу такого же размера (RGBTRIPLE mas[divide][divide]; //divide = 500). Есть массив, каждый елемент которого указывает на соответствующую загруженную матрицу (указатели в матрице постоянно меняются при перемещении - загружаются новые блоки, а старые стираются) (Считываются только нужные блоки). Сам вопрос: Как сделать чтобы при перемещении изображения полосами прокрутки или мышью, актуальные массивы отображались на экране? Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: BRE от Март 08, 2009, 18:03 Такой вопрос, как работают тайловые (tile) карты в 2D играх ты представляшь?
Такие вещи легко обьяснить с листом бумаги и карандашом, а так писанины очень много может получиться. Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Март 08, 2009, 18:24 нет, к сожалению не представляю..., спс - обращу на них внимание...
Согласен что с листом бумаги объясняется за 2 мин, но ... это не листок бумаги Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: BRE от Март 08, 2009, 18:53 Размер карты в точках mapSize = 40000x30000
Размер тайла tileSize = 500x500 Вся карта 80x60 тайлов Для отображения части карты на экране вводим понятия - окно-просмотра (viewport), для простоты - 1000x1000 точки или 2x2 тайла. Это окно, как бы накладывается на карту и его можно по ней двигать. Делаем переменную posViewport, которая показывает положение viewport в точках. Когда posViewport == [0, 0], это значит окно-просмотра находиться в верхнем левом углу карты. Конечные координаты на которые можно сдвинуть это окно [39000,29000]. Теперь нам нужно понять какие тайлы сейчас видны на экране. viewTile.x = posViewport.x / tileSize.x; viewTile.y = posViewport.y / tileSize.y; Пример: posViewport = 1024,370; scrollTile.x = 2; scrollTile.y = 0; Значит нам нужны тайлы (т.к. на viewport помещается только два тайла): 0 1 2 3 4 5 6 7 8 ... 1 * * 2 * * 3 4 5 Но, нам нужно еще сделать скролинг по-пиксельно, поэтому в память загружаем еще по одному ряду и столбцу тайлов. 0 1 2 3 4 5 6 7 8 ... 1 * * + 2 * * + 3 + + + 4 5 Для получения сдвига в точках уже относительно тайлов, делаем: scrollPixel.x = posViewport.x % tileSize.x; scrollPixel.y = posViewport.y % tileSize.y; Для нашего примера: scrollPixel = [ 24, 370 ] Пока так, а то может я непонятно объясняю. ;) Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Март 08, 2009, 19:08 Почему же не понятно, пока все понятно!
Интересный вариант ;) а можно так сделать, чтобы в памяти с каждой стороны было еще допустим по 2 тайла? чтобы если переташить совсем немного к жесткому диску заново не обращаться? Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: BRE от Март 08, 2009, 19:16 Почему же не понятно, пока все понятно! Почему нет, это тебе решать...Интересный вариант ;) а можно так сделать, чтобы в памяти с каждой стороны было еще допустим по 2 тайла? чтобы если переташить совсем немного к жесткому диску заново не обращаться? Теперь к QGraphics: Делаем сцену размером 40000x30000, на ней один к одному размещаем объекты tile, каждый из которых будет знать какую часть карты он должен выводить, но сами картинки еще не загружаем. И теперь в зависимости от текущего сдвига определяем какие тайлы в данный момент видны в viewport и соответствующим тайлам говорим (+их сосетям) говорим загрузить картинки из файла. После изменения текущего сдивга viewport, определяем какие теперь тайлы видны и невидимых говорим удалить картинки из памяти. Можно динамически создавать необходимые тайлы и размещать их на сцене. Вообщем много чего можно сделать. :) Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Март 08, 2009, 19:38 спс, уже пробую... Ты не вкурсе, почему этих тайлов в qt4 нет? Это немного настораживает.
если будут другие варинты - внимательно выслушаю. Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: BRE от Март 08, 2009, 19:40 спс, уже пробую... Ты не вкурсе, почему этих тайлов в qt4 нет? Это немного настораживает. Код
Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Март 08, 2009, 19:51 похоже все намного проще чем я думал )
Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Март 09, 2009, 21:52 Кстати, если комуто надо - могу после того как сделаю выложить исходники!!!
Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Март 14, 2009, 21:05 Делал по разному... много способов пробовал, вот один из способов:
При нажатии на кнопку, поидее память должна освободится, но ..... увы... main.cpp Код: #include <QtGui> tile.h Код: #ifndef TILE_H MyView.h Код: #ifndef _MyView_h_ MyView.cpp Код: #include "MyView.h" Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: Rcus от Март 14, 2009, 21:29 /*:D*/
new QGraphicsRectItem... удалять надо через delete, а еще для удаления всех объектов в контейнере указателей есть qDeleteAll, а еще есть Цитировать void QGraphicsScene::clear () [slot] и создавать QGraphicsRectItem можно через Removes and deletes all items from the scene, but otherwise leaves the state of the scene unchanged. Цитировать QGraphicsRectItem * addRect ( const QRectF & rect, const QPen & pen = QPen(), const QBrush & brush = QBrush() ) запись с указанием сцены последним параметром вообще недокументирована, Код: QGraphicsItem(QGraphicsItem *parent = 0 Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Март 14, 2009, 21:54 Даже если сделать так, в Диспетчере задач память не уменьшится...
Уже не знаю что делать.... в итоге она закончится и программа вылетит... Код: void MyView::pressBotton() Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: Rcus от Март 14, 2009, 22:02 Диспетчер задач никогда не пытался заменить средства по анализу утечек памяти. Можно что-то компилируемое посмотреть? А то я не вижу как удаляются QImage и Tile.
Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Март 14, 2009, 22:26 Я все тексты выложил и все должно компилироваться.
Вот:(http://pic.ipicture.ru/uploads/090314/Lvq20Ewrbc.jpg) Только что обнаружил такую фишку: в развернутом состоянии, когда прокручиваешь изображение прога весит > 20 Мб, и растет при загрузке новых тайлов, в свернутом состоянии прога весит 1.5 Мб, , потом обратно разворачиваешь - опять растет с 20 и дальше... Что за бред :) Цитировать А то я не вижу как удаляются QImage и Tile. Они и не удаляются, я не знаю ка это сделать ;)Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: Khs от Март 14, 2009, 22:33 боюсь предположить что там на картинке)))
Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Март 14, 2009, 22:38 Это курсовая работа )) Картинку взял произвольную, чтобы как можно меньше было монотонных объектов ))
Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: BRE от Март 14, 2009, 22:41 На твоем месте я бы все проектировал иначе.
MyView должен только рисовать, не про какие файлы он знать не должен. Делаешь класс MapImage, который занимается большим файлом. В нем делаешь функцию: QImage *MapImage::getTile( int x, int y ) const которая возвращает тебе указатель на загруженную картинку тайла. Код Нужно еще определить необходимые виртуальные методы (boundingRect и paint), что они должны делать думаю понятно из названия. Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Март 14, 2009, 22:53 Сейчас все исправлю ;) Спс за урок!
Но вот про методы (boundingRect и paint) не понял... их надо переопределить в классе Tile? Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: BRE от Март 14, 2009, 22:55 Сейчас все исправлю ;) Спс за урок! Ага, иначе не получиться создавать объекты Tile.Но вот про методы (boundingRect и paint) не понял... их надо переопределить в классе Tile? Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: SABROG от Апрель 16, 2009, 08:54 Куда-то автор темы пропал, очень уж интересно развитие событий. Удалось память то освободить?
Скомпилил прогу по выложенным исходникам, сконвертил .jpg файл на 8 мегов в .bmp на 38 мегов, переименовал в 1.bmp, но на экране как был черный квадрат малевича так и остался. И наличие и присутствие файла на эту черноту не влияет. Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Апрель 20, 2009, 22:19 Проблемы с памятью уже давно решены )))
Скоро буду реализовывать масштабирование... Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Апрель 20, 2009, 22:42 есть функция, которая возвращает нужный квадрат, только при перетаскивании такого изображения оно подтормаживает, это в общем-то не принципиально, но все же...
В С# есть такая классная штука как сериализация, хотелось бы из файла сразу выдергивать QImage, а не кажный раз при загрузке квадрата попиксельно заполнять его, ну или чтобы заполнение работало побыстрее... Код
divide - размер квадрата = 500 (500х500) Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: SABROG от Апрель 21, 2009, 08:52 В С# есть такая классная штука как сериализация, хотелось бы из файла сразу выдергивать QImage, а не кажный раз при загрузке квадрата попиксельно заполнять его, ну или чтобы заполнение работало побыстрее... В принципе я поискал на тему сериализации/стриминга изображений с помощью методов Qt и пришел к плачевному выводу, что все картинки загружаются в ОЗУ полностью. Задал вопрос об этом на форуме QtCentre и wasyota мне ответил, что надо писать свой плагин, причем делать это надо для всех известных форматов, с нуля. Есть еще вариант с QImage::loadFromData, но он годится, скорее всего, только для bmp, т.к. надо генерить хедер формата и пихать нужный закодированный кусок пикселей в буффер. Как вариант - разбивать картинку другими программами.Пытался использовать ImageMagick. Собрал его с помощью MinGW, но при запуске своей программы, с подлинкованными dll'ками ImageMagick, идет вылет с исключением. Еще вижу такой вариант - тупо скопировать плагины всех форматов и отредактировать их в новые плагины таким образом, чтобы метод QImageReader::setClipRect возвращал картинку без полной её загрузки в ОЗУ. Еще насчет скроллинга QGraphicsView. Мне кажется лучше не использовать реальный скроллинг через scrollbar'ы. Просто установить какой-нибудь QGraphicsItem в размеры нужного окна и делать ему скроллинг на попытки его перетащить в его paint(). Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Апрель 21, 2009, 10:25 Значит остается только попробовать QImage::loadFromData, т.к. я и работаю только с bmp.
Хотя в QImageReader есть такая штука как: bool jumpToImage ( int imageNumber ) bool jumpToNextImage () но только они не хотят работать... надо разобраться как они считывают с одного файла несколько QImage.. Могу и не использовать реальный скролл, вам кажется что от этого скорость повысится? Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: SABROG от Апрель 21, 2009, 11:23 jumpToImage и т.п., к сожалению работают только с анимацией (gif,mng?). Если даже пользовать через них, то большую картинку придется предварительно порезать на квадратики и сгенерить эту анимацию, где каждый фрейм будет этим квадратиком. Опять же придется искать программы или библиотеки, которые смогут сделать эту нарезку не загружая картинку целиком.
Цитировать Могу и не использовать реальный скролл, вам кажется что от этого скорость повысится? Скорее всего только в том случае, если окно будет небольшого размера, а размер тайла и окна будут иметь один размер. Плюс должны быть подгружены еще 8 невидимых соседних тайлов.Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Апрель 21, 2009, 20:22 значит оставлю как есть, скорости и так хватает при отрисовке )))
Попробую только с QImage::loadFromData, может выйдет быстрее... загрузка в QImage Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: SABROG от Апрель 21, 2009, 22:41 Для теста тупо порезал через Total Commander .jpg файл в случайном месте (но явно после хедера). QLabel его свободно открывает. Единственно размер как бы прежний остается из-за чего в удаленном месте просто серые пиксили. Если как-нибудь узнать размеры хедеров, то файлы можно резать на лету. Правда никогда не знаешь какой кусок урезал большой или маленький :)
Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Апрель 24, 2009, 08:38 Попробую... а что за тулса резала? ))
Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: SABROG от Апрель 24, 2009, 17:11 В Total Commander есть функция Split, а в HIEW функция Trunc.
Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Май 05, 2009, 17:51 В Total Commander есть функция Split, а в HIEW функция Trunc. А у меня что-то не выходит...Подскажите как можно быстро загрузить в QImage данные из RGBTRIBLE, которая находится в оперативке... Или же формировать один файл, с которого можно читать заданный Image... Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Май 11, 2009, 19:09 Всем спасибо, все готово, в том числе и зуммирование!!! На днях сдаю курсовую :)
Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: break от Май 17, 2009, 03:41 Вопрос к знатокам - а правильно ли изначально использоватьо огромный файл картинки? (возможно буду решать подобную задачу - только не курсовую а программу для людей)
Если предположить что решаемаяч задача - карта местности - может эти тайлы (изображение подложки карты) должны были отдельно на диске лежать tile01.jpg, tile02.jpg И вообще всякие фотошопы как с файлом 40000 на 30000 справляются? Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: transto от Август 04, 2009, 03:13 Всем спасибо, все готово, в том числе и зуммирование!!! и как ты отобразил полностью всю картинку (зуммированную)? надо изменять разрешение картинки в фоновом режиме и загружать уже обработанный битмап в тайлы? Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Август 10, 2009, 16:29 и как ты отобразил полностью всю картинку (зуммированную)? надо изменять разрешение картинки в фоновом режиме и загружать уже обработанный битмап в тайлы? Я конвертировал картинку с разным разрешением на диск, в итоге получилось несколько файлов с разными размерами (масштаб 1:1, 1:2, 1:4 и т.д.). а когда нужно было отобразить в нужном разрешении - открывал нужный файл. Согласен, это извращение, но так и нужно было сделать. Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: sk8ter от Август 10, 2009, 16:35 Вопрос к знатокам - а правильно ли изначально использоватьо огромный файл картинки? (возможно буду решать подобную задачу - только не курсовую а программу для людей) Если предположить что решаемаяч задача - карта местности - может эти тайлы (изображение подложки карты) должны были отдельно на диске лежать tile01.jpg, tile02.jpg И вообще всякие фотошопы как с файлом 40000 на 30000 справляются? мой одногрупник скачал на Java движок GoogleEarth и немного его модернизировал... так что было на диске множество файлов и нужные подгружались автоматически, он же и разбивал большой рисунок на мелкие... Насчет правильно ли использовать изначатьно такой большой файл - отвечу только то, что нам его дали потому что его легче было освоить. А вот насчет фотошопа - он походу конвертирует файл в свою структуру данных (для ускорения работы) и с ним работает. Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: Igors от Август 10, 2009, 19:10 Добрый день
И вообще всякие фотошопы как с файлом 40000 на 30000 справляются? Базовая техника одна. Никто не держит изображение в RAM целиком. Файл распаковывается во временный файл (или в общий swap файл) "по страницам" (по tile, по квадратикам - называйте как хотите). В памяти хранится "карта" страницstruct CImagePage { CImagePage * mPrev; // prev page in list CImagePage * mNext; // next page in list long long mFilePos; // file position void * mPixels; // pixels or NULL for purged page bool mDirty; // page has been modofied ... }; Загруженные страницы хранятся в списке 1, не загруженные - в списке 2. Если затребованная страница не загружена, она загружается и переносится в голову списка 1. Если длина списка 1 превышает заданную, страница в хвосте списка 1 выгружается и переносится в список 2 . Счетчик "не больше N страниц в памяти" определяет скорость/расход памяти Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: break от Август 10, 2009, 21:49 Цитировать мой одногрупник скачал на Java движок GoogleEarth и немного его модернизировал...[/ quote] где такое скачать можно? Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: Сергей(ser) от Декабрь 14, 2010, 16:27 Всем спасибо, все готово, в том числе и зуммирование!!! На днях сдаю курсовую :) sk8ter !!!! выложи исходники plz... Название: Re: QGraphicsView, QGraphicsScene для отображения огромного файла (2хОЗУ) Отправлено: slim от Январь 06, 2011, 19:39 советую посмотреть на такую штуку http://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D0%B3%D0%B0%D1%82%D0%B5%D0%BA%D1%81%D1%82%D1%83%D1%80%D0%B0
|