Solved QImageReader second read() results in empty image
-
Hallo,
I currently implementing a map viewer utilizing QImageReader. Everything works well until i call the read() method a second time.
QImageReader reader( "../../../../in/image.jpg"); reader.setClipRect(QRect(0, 0, 1500, 800)); reader.canRead(); //returns true QImage image = reader.read();
up to now everything works well.
reader.device()->seek(0); reader.setClipRect(QRect(0, 0, 500, 400)); reader.canRead(); // returns false QImage temp_image = reader.read(); // null image
The second read() call results in a null image. I already tried to fix the problem reseting the handler using reader.device()->seek(0);
But the result was the same - no image.Calling error() or errorString() before the second call of read() always returns "Unknown error". After the second read() call the method returns "Unable to read image data".
I working with:
Qt 5.12.0
Qt Creator 4.8.0
macOS 10.14Thanks
-
@MichMich
For a start check the return result ofreader.device()->seek(0)
. Though if it returnsfalse
I don't know what you're going to do about it.Since your question has gone unanswered, unless you want to look through the
QImageReader
(QImageIOHandler
) source code, you may have to guess that it's not aware of your "seek" alteration, e.g. perhapsNote:
QImageReader
assumes exclusive control over the file or device that is assigned. Any attempts to modify the assigned file or device during the lifetime of theQImageReader
object will yield undefined results.and perhaps create a new
QImageReader
off the file again instead. -
@MichMich
Hi
You could also try setFileName
It might reset state of the reader. -
Hallo, thank's for the response.
@JonB
reader.device()->seek(0)
returnstrue
, it sets the position correctly to 0, i checked the previouse value.
I also tried to debug into theQImageReader
source but i couldn't jump into the source. I mapped the debug path to the Qt sources, but this also doesn't work. I am currently building Qt from source to check if i can debug the reader.According to the error message i assume that the problem occurs in the row 1313:
!d->handler->read(image)
.@mrjj
CallingsetFileName()
before the second read everything works as expected. I receive an image.
This could be a possible solution, but i am afraid that it could be adversely to the performance calling setFileName() repetitive. Each call will delete the old IODevice object and create a new one.Some background to my tool:
My map viewer should be able to load large images. Also i have enough RAM and loading 1GB images should be now problem (but i didn't tested it up to now), i want to allow to load even larger images if necessary. I usesetClipRect()
to get a part of the image. If the user pans the image i want to dynamically load the according part of the image shifted by a delta. But i think i have to try callingsetFileName()
repetitive and check the performance.Or does someone have another advice?
-
@MichMich
I do not know why the code fails to re-load. But given where you are now, although resetting the filename does indeed create a newQImageReader
(which then works) with some overhead, on the grand scale of things if you are going to be loading 1GB+ from disk the time to do that should way outweigh any time to re-open the file, so you may have to live with it. Make sure if you do that the previousQImageReader
with its image gets disposed properly so that it does not retain any memory footprint. -
Strange - looks like a jpg problem
QImageReader reader("qticon64.jpg"); //QImageReader reader("qticon64.png"); reader.setClipRect(QRect(0, 0, 32, 32)); qDebug() << "can read 1:" << reader.canRead(); QImage image = reader.read(); qDebug() << image; reader.device()->seek(0); qDebug() << "can read 2:" << reader.canRead(); image = reader.read(); qDebug() << image;
Using a png file works ...
-
@Christian-Ehrlicher
FYI, https://trac.ffmpeg.org/ticket/6113 reports this issue for "JPEG file seek". Though whether that's a red-herring or of some indicative interest I don't know.... -
The Qt internal QJpegHandler simply can't read a file twice due to it's internal state handling - after the image was read, the state is ReadingEnd which prevents a further re-read. Since there is also no chance to get a signal when the device read pointer was (re)set I don't see an easy way to fix it.
-
I see, so the easiest way and best option according to the performance is to change from jpg files to png files.
I already checked it out and it works as assumed.
Thank you all for your help. I will mark the topic as solved.