Results 1 to 8 of 8

Thread: multithreaded QImageReader

  1. #1
    Join Date
    Jan 2011
    Posts
    22
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default multithreaded QImageReader

    Hello,

    I am trying to create image tiles that load asynchronously as they are displaying in a QGraphicsView. I have subclassed QGraphicsItem, and overloaded the pain method with the following:

    Qt Code:
    1. void RasterTile::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget)
    2. {
    3. if(image.isNull())
    4. {
    5. TilePainter=painter;
    6. TileOption=option;
    7. TileWidget=widget;
    8. future = QtConcurrent::run(this, &RasterTile::LoadTilePixmap);
    9. watcher.setFuture(future);
    10.  
    11. }else
    12. {
    13. QRectF imageRect = image.rect();
    14. painter->drawImage(imageRect, image);
    15. }
    16.  
    17. }
    To copy to clipboard, switch view to plain text mode 

    Which calls the following in its own thread:

    Qt Code:
    1. QImage RasterTile::LoadTilePixmap()
    2. {
    3. QMutexLocker locker(&mutex);
    4.  
    5. QImage img(nBlockXSize, nBlockYSize, QImage::Format_RGB32);
    6.  
    7. QRect rect(tilePosX*nBlockXSize, tilePosY*nBlockYSize, nBlockXSize, nBlockYSize);
    8.  
    9. reader->setClipRect(rect);
    10. reader->read(&img);
    11. if(reader->error())
    12. {
    13. qDebug("Not null error");
    14. qDebug()<<"Error string is: "<<reader->errorString();
    15. }
    16. return img;
    17.  
    18. }
    To copy to clipboard, switch view to plain text mode 

    mutex is a static member of my class which is defined in the .h, and in the cpp

    QMutex RasterTile::mutex;

    This code seems to malfunction. If i have like 5 tiles of an image, they all seem to get some data in them, but it is often scrambled and such. Occaisionally one will load all of the image data correctly. This leads me to believe I have something going wrong with the threading. Each tile has its own instance of a QImageReader, all pointing to the same file.

    What am I doing wrong here?

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: multithreaded QImageReader

    What is the use of the mutex?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Jan 2011
    Posts
    22
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: multithreaded QImageReader

    Well, it was leftover sort of. I had originally created one QImageReader, passed that pointer to all tiles, and used it to keep multiple threads for reading from the same file at once because I was getting some errors from libjpeg, libpng, etc. This made me think that was the issue.

    Presently I get no errors, the image just doesnt load and look correct.

    Well, it was leftover sort of. I had originally created one QImageReader, passed that pointer to all tiles, and used it to keep multiple threads for reading from the same file at once because I was getting some errors from libjpeg, libpng, etc. This made me think that was the issue.

    Presently I get no errors, the image just doesnt load and look correct.

    Here is the full code from my first try - passing a pointer to the reader into each tile:

    Header:

    Qt Code:
    1. class RasterTile : public Tile
    2. {
    3. public:
    4. RasterTile (QImageReader *reader, int nBlocksX, int nBlocksY, int xoffset, int yoffset, int nXBlockSize, int nYBlockSize);
    5.  
    6. protected:
    7. QImageReader *reader;
    8. void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);
    9. QImage LoadTilePixmap();
    10. private:
    11. mutable QMutex mutex;
    12. };
    To copy to clipboard, switch view to plain text mode 

    Cpp:

    Qt Code:
    1. #include "rastertile.h"
    2.  
    3. RasterTile::RasterTile(QImageReader *reader, int nBlocksX, int nBlocksY, int xoffset, int yoffset, int nXBlockSize, int nYBlockSize)
    4. : Tile(nBlocksX, nBlocksY, xoffset, yoffset, nXBlockSize, nYBlockSize)
    5. {
    6. this->reader = reader;
    7. connect(&watcher,SIGNAL(finished()),this,SLOT(updateSceneSlot()));
    8. }
    9.  
    10.  
    11. void RasterTile::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget)
    12. {
    13. if(image.isNull())
    14. {
    15. TilePainter=painter;
    16. TileOption=option;
    17. TileWidget=widget;
    18. future = QtConcurrent::run(this, &RasterTile::LoadTilePixmap);
    19. watcher.setFuture(future);
    20.  
    21. }else
    22. {
    23. QRectF imageRect = image.rect();
    24. painter->drawImage(imageRect, image);
    25. }
    26.  
    27. }
    28.  
    29. QImage RasterTile::LoadTilePixmap()
    30. {
    31. QMutexLocker locker(&mutex);
    32. QImage img(nBlockXSize, nBlockYSize, QImage::Format_RGB32);
    33. QRect rect(tilePosX*nBlockXSize, tilePosY*nBlockYSize, nBlockXSize, nBlockYSize);
    34. reader->setClipRect(rect);
    35. reader->read(&img);
    36. return img;
    37.  
    38. }
    To copy to clipboard, switch view to plain text mode 



    How I am instantiating the classes:

    Qt Code:
    1. for(int i =0; i < nXBlocks; i++)
    2. {
    3. for(int j = 0; j < nYBlocks; j++)
    4. {
    5. RasterTile *ipi = new RasterTile(reader,nXBlocks, nYBlocks, i, j, nXBlockSize, nYBlockSize);
    6.  
    7. }
    8. }
    To copy to clipboard, switch view to plain text mode 

    After this try, is when i started trying to make the mutex private, and then also passing in just the file name so each Tile could create it's own reader.

    "image" is a QImage that gets set to the img from "LoadTilePixmap()" and is set in the Tile::updateSceneSlot()

  4. #4
    Join Date
    May 2011
    Posts
    23
    Thanks
    3
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Cool Re: multithreaded QImageReader

    and overloaded the pain method
    Weeeell when you overload the pain method that's what you get :-D
    (Sorry i had to have a go, nice one)

    OK, back to the problem. Well, in my opinion, by the description of your case, you do not need threading, you can do without (i.e. you're only reading from the image at different locations - not read/write). You can still create your RasterTiles at different times and still be able to read from the same image.
    In other words, from the description of your problem, there is no basis for threading.

    Best of lunch ... I mean luck ;-)

    Jean

  5. #5
    Join Date
    Jan 2011
    Posts
    22
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: multithreaded QImageReader

    Why do you say I wouldnt need threading? I am loading really large images. I have a loop in my GUI that figures out how many tiles I need, creates them all, groups and positions them in the right place, and then allows the user to go do other things while the image is loading. If I try to move the image, and a whole bunch of tiles need to load, the program will freeze while all of those tiles load. This will prevent a user from panning to a certain location in the image, and having the tiles load as they pan. It makes for a nicer user experience (think of google maps)


    Added after 5 minutes:


    I did just have a thought - when I call "setClipRect" on the reader, does that effectively trash all of the data that was not within the rect? Maybe reader is having it's data truncated, and that is why other threads have problems reading?
    Last edited by dcole; 23rd June 2011 at 22:23.

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: multithreaded QImageReader

    I think that you can't access the same file concurrently from within more than one thread. Apparently, despite the mutex, you have some concurrent access somewhere. And it seems all your thread are using the same image reader which also might be leading to problems. Try creating the reader in the LoadTilePixmap method.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    May 2011
    Posts
    23
    Thanks
    3
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Post Re: multithreaded QImageReader

    ..freeze while all of..
    From this quoted description, you do need threading. Your first description/text/explanation didnot show anywhere that you needed it. That's what I meant.

    However, having said that, from what you've just said, your threading model is still not justified i.e. you don't need to thread up your RasterTile class for what you're trying to do with it. Instead, you need to thread up between your RasterTile and the rest of your GUI (the user experience part).
    You don't need to thread up your RasterTile class because you are reading different parts from your image, even if they are huge like the world!

    The fact that some parts are returned scrambled is nothing to do with threading unless this dictates tile coordinates in your file, which from your description is nowhere mentioned.

    Fix/check your reader first then Choose your threading model after.

    All the best.

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: multithreaded QImageReader

    Actually he doesn't need threading. There is a number of solutions one can use to avoid freezing the GUI -- [wiki]Keeping the GUI Responsive[/wiki]. The "step by step" approach seems applicable here.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. QimageReader Unknown Error
    By bhaskar in forum Newbie
    Replies: 1
    Last Post: 2nd June 2010, 09:24
  2. QImageWriter QImageReader and QSocket
    By jordip in forum Qt Programming
    Replies: 0
    Last Post: 11th March 2010, 19:29
  3. Use QImageReader to test image files
    By jvillain in forum Qt Programming
    Replies: 1
    Last Post: 23rd March 2009, 11:05
  4. Replies: 2
    Last Post: 7th November 2006, 13:49
  5. QImageReader with Qt::FastTransformation???
    By sepp in forum Qt Programming
    Replies: 1
    Last Post: 21st March 2006, 14:56

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.