UPD .Итак, поскольку мой вопрос был встречен в основном путаницей, я постараюсь исправить его, сузив проблему до самого необходимого.
Дано:
большое изображение размером в несколько Гб, назовите его img.jpg
(.png
/ .bmp
);
координаты небольшого фрагмента на изображении rect = QRect(x,y,w,h)
;
Запись:
- функция, которая загружает фрагмент
rect
с изображения на диске в QPixmap
;функция должна вызываться часто.
Попытка решения и проблемы:
- первое решение было использовать
QImageReader
, который имеет методsetClipRect(QRect)
для указания области на изображении, которое будет загружено.Отлично, правда?Проблема в том, что метод read()
вернет QImage
только при первом вызове.После этого будут возвращаться пустые изображения с сообщением об ошибке «Невозможно прочитать данные изображения».Перематывание QIOReader
, которое QImageReader
использует до нуля, не помогает.Создание QImageReader
снова стоит очень дорого в производительности.
Ссылки:
- Здесь - вопрос 2011 годапо существу с той же проблемой (мой вопрос может быть дубликатом).Человек пытается сделать то же самое, что и я, и сталкивается с той же проблемой.Он спрашивает, почему его читатель дает ему «Невозможно прочитать данные изображения», хорошо, потому что он не читает дважды, и неясно, как это исправить.
- Здесь они спрашивают в основном то же самоевопрос и решение - перемотать QIODevice, позвонив по номеру
reader->device()->seek(0);
.Проблема в том, что он не работает: после перемотки устройства reader->read()
по-прежнему возвращает пустые QImage
с и выдает сообщение об ошибке «Невозможно прочитать данные изображения». - Здесь , здесь и здесь - сообщения, в которых обсуждается проблема загрузки больших изображений в тайлы в Qt, которые помогли мне реализовать мое текущее решение.
Ниже приведен оригинальный пост с более подробной информацией.
Я пишу виджет, который загружает изображение фрагментарно и отображает его в QGraphicsScene
с плитками, которые могут бытьзагружается и выгружается в зависимости от их видимости в окне просмотра.Плитки показывают заполнитель, когда они выгружены, и они загружают соответствующий фрагмент в QPixmap
по требованию.Предполагается, что виджет может открывать изображения размером до нескольких гигабайт, не занимая много памяти.
Я планировал сделать так, чтобы на каждой плитке было изображение, открытое и готовое для чтения из определенного места.Я использую QImageReader
, который позволяет вам установить прямоугольник, определяющий область изображения для загрузки.Но оказалось, что после установки прямоугольника я могу прочитать изображение только один раз .Чтобы загрузить его снова, мне нужно создать новый экземпляр QImageReader
, который откроет файл заново .Я попытался открыть ~ 2Гб изображения с плитками 256x256, и он загружается очень медленно: на моем компьютере для загрузки одного экрана HD требуется около 30 секунд.
Это код, который я сейчас использую для загрузки плиток:
void TileLoader::load(int posx, int posy, int w, int h, QString filename) {
QImageReader reader(filename);
QRect tile(posx, posy, w, h);
reader.setClipRect(tile);
QImage image(w, h, QImage::Format_RGB32);
reader.read(&image);
emit tileLoaded(QPixmap::fromImage(image));
}
Вместо того, чтобы каждый раз создавать экземпляр QImageReader
, я надеялся передать существующий в качестве аргумента.Но, к сожалению, это работает только один раз, поэтому QImageReader
- не тот путь.Но что это такое?
Я также могу воссоздать медленную загрузку с обычными изображениями, такими как ~ 1000x1000 пикселей, если я установил размер плитки в 16x16.Я вижу маленькие плитки, разворачивающие изображение перед моими глазами волнообразным движением в течение примерно 10 секунд, что само по себе прекрасно, но совершенно непрактично с точки зрения поставленной задачи.
![enter image description here](https://i.stack.imgur.com/Dma6P.jpg)
![enter image description here](https://i.stack.imgur.com/5NQc8.jpg)
Итак, вопрос: есть ли способ сохранить мой файл изображения открытым на все время?плитка существует, поэтому она может быстро прочитать ее части?