Чтение одного и того же фрагмента большого изображения с диска несколько раз без закрытия файла - PullRequest
0 голосов
/ 26 октября 2018

UPD .Итак, поскольку мой вопрос был встречен в основном путаницей, я постараюсь исправить его, сузив проблему до самого необходимого.

Дано:

  • большое изображение размером в несколько Гб, назовите его img.jpg (.png / .bmp);

  • координаты небольшого фрагмента на изображении rect = QRect(x,y,w,h);

Запись:

  • функция, которая загружает фрагмент rect с изображения на диске в QPixmap;функция должна вызываться часто.

Попытка решения и проблемы:

  • первое решение было использовать QImageReader, который имеет методsetClipRect(QRect) для указания области на изображении, которое будет загружено.Отлично, правда?Проблема в том, что метод read() вернет QImage только при первом вызове.После этого будут возвращаться пустые изображения с сообщением об ошибке «Невозможно прочитать данные изображения».Перематывание QIOReader, которое QImageReader использует до нуля, не помогает.Создание QImageReader снова стоит очень дорого в производительности.

Ссылки:

  1. Здесь - вопрос 2011 годапо существу с той же проблемой (мой вопрос может быть дубликатом).Человек пытается сделать то же самое, что и я, и сталкивается с той же проблемой.Он спрашивает, почему его читатель дает ему «Невозможно прочитать данные изображения», хорошо, потому что он не читает дважды, и неясно, как это исправить.
  2. Здесь они спрашивают в основном то же самоевопрос и решение - перемотать QIODevice, позвонив по номеру reader->device()->seek(0);.Проблема в том, что он не работает: после перемотки устройства reader->read() по-прежнему возвращает пустые QImage с и выдает сообщение об ошибке «Невозможно прочитать данные изображения».
  3. Здесь , здесь и здесь - сообщения, в которых обсуждается проблема загрузки больших изображений в тайлы в 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

enter image description here

Итак, вопрос: есть ли способ сохранить мой файл изображения открытым на все время?плитка существует, поэтому она может быстро прочитать ее части?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...