Results 1 to 14 of 14

Thread: Printing QwtPlot on QImage from inside a thread

  1. #1
    Join Date
    Oct 2006
    Location
    New Delhi, India
    Posts
    2,467
    Thanks
    8
    Thanked 334 Times in 317 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Printing QwtPlot on QImage from inside a thread

    Hi, I am new to Qwt,,
    I am facing a problem in which I get crash when I call QwtPlot::replot or QwtPlot::Print from inside a thread. My use case is, I need to send data from a thread, and to speed up things I wanted to print the plot and send the image.
    But when I call replot or print,,, I get the following as attached in the image.
    I guess it is because we cant paint to QPixmap from thread, and I have seen that QwtPlot uses Qpixmap as cache. But i also tried disabling the caching by -
    plot->canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached,fals e); but still getting crash.

    From call stack I see that qwt accesses font metric and -
    In QWidget::metric() --
    HDC gdc = qt_win_display_dc();

    In Q_GUI_EXPORT HDC qt_win_display_dc() // get display DC
    {
    Q_ASSERT(qApp && qApp->thread() == QThread::currentThread());

    Thats where it fails.

    I searched the forum but cudnt get a solution to my problem. I just need the plot in QImage inside the thread. I need it to send to some other client. I am very much stuck and help will be highly appreciated.
    Attached Images Attached Images

  2. #2
    Join Date
    Aug 2009
    Posts
    52
    Thanked 10 Times in 10 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Printing QwtPlot on QImage from inside a thread

    QWidget and all its subclasses, are not reentrant. They can only be used from the main thread.

  3. #3
    Join Date
    Oct 2006
    Location
    New Delhi, India
    Posts
    2,467
    Thanks
    8
    Thanked 334 Times in 317 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Printing QwtPlot on QImage from inside a thread

    Quote Originally Posted by dbzhang800 View Post
    QWidget and all its subclasses, are not reentrant. They can only be used from the main thread.
    I know that. But there must be some way I can use QImage from the thread to print the plot ?

  4. #4
    Join Date
    Aug 2009
    Posts
    52
    Thanked 10 Times in 10 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Printing QwtPlot on QImage from inside a thread

    Quote Originally Posted by aamer4yu View Post
    I know that. But there must be some way I can use QImage from the thread to print the plot ?
    so why are you still trying to use QwtPlot in your thread ?

  5. #5
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,311
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Printing QwtPlot on QImage from inside a thread

    Quote Originally Posted by aamer4yu View Post
    But there must be some way I can use QImage from the thread to print the plot ?
    I never tried it myself, but QwtPlot::print() in combination with a QImage should be possible. But moving an operation to a second thread doesn't speed up anything.

    Guess what you want to do is to distribute the composition of the plot to several threads running parallel. This is possible for rendering a spectrogram ( implemented in trunk ), but not for operations using a QPainter. There might be operations like polygon clipping, that could benefit from multithreading, but ...

    Anyway if you have performance issues I would expect more succes from algorithmic strategies (like f.e. incremental painting, introducing level of details).

    Uwe

  6. #6
    Join Date
    Oct 2006
    Location
    New Delhi, India
    Posts
    2,467
    Thanks
    8
    Thanked 334 Times in 317 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Printing QwtPlot on QImage from inside a thread

    I never tried it myself, but QwtPlot:rint() in combination with a QImage should be possible.
    No it was not working as far as I tried. however QwtPlot::drawCanvas() was working but I was not getting correct image.

    Well, my problem is not much of multi threading, I read data from a device in a thread and need to send spectrogram of it to some client. Since the class which reads data from device is in thread, I need to use plot from that thread itself.

    I would say if you can work around this problem it would be really nice, since many others might be facing this problem. It would be nice if one could call Qwt:rint() from thread on a QImage.
    Currently I tried a hack - I send signal to main class, and callback the sending QImage function from that main thread,, need to test,, but still its a hack

  7. #7
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,311
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Printing QwtPlot on QImage from inside a thread

    Well, my problem is not much of multi threading, I read data from a device in a thread and need to send spectrogram of it to some client. Since the class which reads data from device is in thread, I need to use plot from that thread itself.
    This is no argument for distributing paint operations across different threads.

    But if you mean by spectrogram the same what is meant by a QwtPlotSpectrogram you have to render a QImage by mapping values int colors. As a QImage is simply an array of RGB values I don't see why you need the QwtPlot widget for this or why it shouldn't be possible to do it in a separate thread.
    I would say if you can work around this problem it would be really nice, since many others might be facing this problem.
    Well if you would post your requirements ( of your application not of your implementation) I could try to understand if it something of common interest. But at the moment all I see is that you have problems with an implementation using the wrong calls for a situation I don't know.

    Uwe

  8. #8
    Join Date
    Oct 2006
    Location
    New Delhi, India
    Posts
    2,467
    Thanks
    8
    Thanked 334 Times in 317 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Printing QwtPlot on QImage from inside a thread

    Well, my requirement for application is as follows -
    Read data from a spectrometer and plot its values(wavelength vs intensities) on a QImage / QPixmap.[This is a simple 2D plot, NOT 3D] The values we get from spectrometer are array of double. The reading from spectrometer is done in a thread.

    I could very well send the data to client and do the rendering there. But to speed up things, I wanted to send image instead of data from the thread where reading from spectrometer is taken.

    Current implementation-
    Using QwtPlot / QwtPlotCurve to plot the same. I call QwtPlotCurve::setData to set the values and try to get a print of QwtPlot on Qimage.

    I hope am a bit more clear this time. I didnt look into QwtPlotSpectrogram, since I needed a simple plot of intensities for given wavelengths...something like scatter diagram in excel.
    Am not sure if other class will do better job.
    Can you help ??

  9. #9
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,311
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Printing QwtPlot on QImage from inside a thread

    Quote Originally Posted by aamer4yu View Post
    Well, my requirement for application is as follows -
    Read data from a spectrometer and plot its values(wavelength vs intensities) on a QImage / QPixmap.
    Isn't the requirement of your application to plot to screen - if not why do you need a QwtPlot widget ?
    Isn't QPixmap/QImage only part of your implementation trying to speed up the rendering process ?
    ...something like scatter diagram in excel.
    Rendering your curve points to an image and flushing the image for each point doesn't speed up anything - in fact it is probably the worst (horrible slow) implementation I can imagine.

    If your axis scales don't change for each point you could try to paint your points incrementally. This is supported on X11 (best) and on platforms using the raster paint engine ( f.e windows). Have a look at the realtime example and check if this is the performance you expect from your application.

    In qwt trunk you find an oscilloscope example, that shows an implementation with a thread producing values and how they are painted incrementelly in the GUI thread.

    But If you don't have many points and high refresh rates (several frames per second) I wouldn't spend much time on optimizations and use QwtPlot in its default settings (beside disabling the paint cache) - using replot for each update.

    Uwe

  10. #10
    Join Date
    Oct 2006
    Location
    New Delhi, India
    Posts
    2,467
    Thanks
    8
    Thanked 334 Times in 317 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Printing QwtPlot on QImage from inside a thread

    Isn't the requirement of your application to plot to screen - if not why do you need a QwtPlot widget ?
    Isn't QPixmap/QImage only part of your implementation trying to speed up the rendering process ?
    Well, we have a separate application for gui. This thread is another app which is meant for communicating with devices. Now when you get data from the device we need to send it to the gui app through sockets. The image is finally shown there. So using QImage is part of speeding things for data transfer since data of Qimage will be smaller than the actual data.

    Rendering your curve points to an image and flushing the image for each point doesn't speed up anything - in fact it is probably the worst (horrible slow) implementation I can imagine.
    Well am not plotting in the same app as explained above.. and sending QImage does speed up things.

    I have tried a hack.. from the thread I emit a signal to main thread of device app. This then calls a function of that device class which sends the qimage to gui app through socket. and this is working and it does speed up things. But what I want is,, instead of emitting signal and calling the function from main thread, I want to directly call the function.

  11. #11
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,311
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Printing QwtPlot on QImage from inside a thread

    Well am not plotting in the same app as explained above.. and sending QImage does speed up things.
    Assuming your plot has a size of 500x500 pixels your image will have a size of 250000 * 4 bytes = 1MB. After you rendered your point to the image and sent the complete image over the socket to your GUI application the image needs to be sent through the graphics pipeline of Qt.

    Do you really expect, that this is faster than sending 2 doubles over a socket and painting it incrementally ( skipping a lot of steps of the Qt graphics pipeline ) to the plot widget ? F.e for a XCross symbol on X11 this means only 2 x XDrawLine - probably hardware accelerated.
    I have tried a hack.. from the thread I emit a signal to main thread of device app. This then calls a function of that device class which sends the qimage to gui app through socket.
    Does it mean you have an application with a GUI thread, that has an invisible plot widget. The only purpose of this widget is, that you want to render an offscreen image that is sent to a different aplication, that is able to display this image - probably not in a QwtPlot widget ?
    ... and this is working and it does speed up things
    Compared to what ?

    Anyway - Qwt isn't able to render a plot without a plot widget. The reason for this is that many attributes of the plot are stored in members of the plot widget ( having a QwtPlotScene object like in the QGV framework is on my TODO list ). So you need to have a plot widget and this needs to be allocated in the GUI thread.

    But QwtPlot::print to a QImage should be possible from another thread. If it doesn't work in your application you need to report what the problems are in detail.

    But IMO the overhead of rendering the image in a different thread is the last thing you have to worry.

    Uwe

  12. #12
    Join Date
    Oct 2006
    Location
    New Delhi, India
    Posts
    2,467
    Thanks
    8
    Thanked 334 Times in 317 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Printing QwtPlot on QImage from inside a thread

    Does it mean you have an application with a GUI thread, that has an invisible plot widget. The only purpose of this widget is, that you want to render an offscreen image that is sent to a different aplication, that is able to display this image - probably not in a QwtPlot widget ?
    Yes.
    But the plotting is not incremental. One takes a snap of spectrum from the spectrometer, makes 3 different curves based on previous data. and plots it. Each time whole new set of data is computed.
    Assuming your plot has a size of 500x500 pixels your image will have a size of 250000 * 4 bytes = 1MB.
    Well after paying attention to this, I found indeed sending data through image was larger. With image I found the message to be 940KB while without image it was 153KB. Seems its a matter of how the data was parsed. All messages are sent in xml. So in case of image, image data was stored in CDATA section. One CDATA for 3 curves, while in other case, values were sent as attribute, double array converted in base64. So it seems things were faster with image even with larger data because of xml parsing.
    But IMO the overhead of rendering the image in a different thread is the last thing you have to worry.
    I admit you are right.

    But QwtPlot:rint to a QImage should be possible from another thread. If it doesn't work in your application you need to report what the problems are in detail.
    The Qwt:rint crash is still a problem. Lets say I function device::sendData, which calls qwtPlot:rint() function. device class is a member of another class deviceManager which is a thread. owner of deviceManager is say mainManager. Now say if i call device::sendData from another function device::readSpectrum then program crashes in device::sendData.
    But if I emit a signal from device::readSpectrum to a slot(slotSendData) in mainManager, and call device::sendData from the mainManager::slotSendData, then it works fine.
    The call stack in case of crash is -
    Qt Code:
    1. > QtCored4.dll!qt_message_output(QtMsgType msgType=QtFatalMsg, const char * buf=0x097e4260) Line 2019 C++
    2. QtCored4.dll!qFatal(const char * msg=0x67238224, ...) Line 2216 + 0x29 bytes C++
    3. QtCored4.dll!qt_assert(const char * assertion=0x65914cac, const char * file=0x65914c90, int line=902) Line 1786 + 0x16 bytes C++
    4. QtGuid4.dll!qt_win_display_dc() Line 902 + 0x47 bytes C++
    5. QtGuid4.dll!QWidget::metric(QPaintDevice::PaintDeviceMetric m=PdmDpiY) Line 1658 + 0x5 bytes C++
    6. QtGuid4.dll!QPaintDevice::logicalDpiY() Line 96 + 0x16 bytes C++
    7. QtGuid4.dll!QFont::QFont(const QFont & font={...}, QPaintDevice * pd=0x09781648) Line 709 + 0x8 bytes C++
    8. qwtd5.dll!03550fc8()
    9. [Frames below may be incorrect and/or missing, no symbols loaded for qwtd5.dll]
    10. qwtd5.dll!03550697()
    11. QtCored4.dll!QString::~QString() Line 866 + 0x11 bytes C++
    12. qwtd5.dll!03552032()
    13. qwtd5.dll!0351ad2c()
    14. qwtd5.dll!0354a55d()
    15. ntdll.dll!7c9623e0()
    16. ntdll.dll!7c91005d()
    17. msvcr80d.dll!_free_base(void * pBlock=0x095ee988) Line 109 + 0x13 bytes C
    18. qwtd5.dll!03549373()
    19. msvcr80d.dll!_free_dbg(void * pUserData=0x00000005, int nBlockUse=25) Line 1225 + 0x7 bytes C++
    20. msvcr80d.dll!free(void * pUserData=0x012fa350) Line 1178 + 0xb bytes C++
    21. qwtd5.dll!03590016()
    22. qwtd5.dll!0358f699()
    23. qwtd5.dll!0351c80f()
    24. qwtd5.dll!0351ecdb()
    25. qwtd5.dll!03590132()
    26. qwtd5.dll!0356addd()
    27. qwtd5.dll!03566606()
    To copy to clipboard, switch view to plain text mode 

    In short, you are right about image overhead. And I have given some detail about the print crash. Can you help ,,, may be I am missing something or may be doing some mistake.

  13. #13
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,311
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Printing QwtPlot on QImage from inside a thread

    All messages are sent in xml.
    Well, this is second in the ranking of really slow implementations. The bottleneck of this solution is the XML parser not the amount of data you have to send over the socket. If you have ever worked with SVG you will know that the parser takes much longer, than the painting itsself.

    Why don't you simply send the points as they are - everything could be so easy.

    ... print crash.
    All I can see is, that the crash is in Qt, but without knowing the Qwt calls in your stack I can't tell you if it is possible to avoid the QFont initialization.

    Check the paint device in the QFont constructor: is it your image or one of the widgets ( or internal pixmaps ) of your plot widget ?

    Uwe

  14. #14
    Join Date
    Oct 2006
    Location
    New Delhi, India
    Posts
    2,467
    Thanks
    8
    Thanked 334 Times in 317 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Printing QwtPlot on QImage from inside a thread

    Why don't you simply send the points as they are - everything could be so easy.
    I wish I could.. but cant.

    Check the paint device in the QFont constructor: is it your image or one of the widgets ( or internal pixmaps ) of your plot widget ?
    I will do that when I get time, right now I got busy with some other work.
    Thanks a lot for your help till now

Similar Threads

  1. print picture (QImage) from non GUI thread
    By valeron in forum Qt Programming
    Replies: 1
    Last Post: 30th April 2013, 19:35
  2. QwtPlot inside QScrollArea
    By mastupristi in forum Qwt
    Replies: 3
    Last Post: 13th October 2009, 04:28
  3. KDE/QWT doubt on debian sarge
    By hildebrand in forum KDE Forum
    Replies: 13
    Last Post: 25th April 2007, 06:13
  4. Replies: 10
    Last Post: 20th March 2007, 22:19
  5. [QT4] QThread and printing a QList<QPixmap>
    By KShots in forum Qt Programming
    Replies: 3
    Last Post: 24th April 2006, 21:44

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.