Program crashes from QWebFrame::Render() method
-
I would like to create an image of the current loaded web page. As I see there is a way to do it :). The proper way is described in QWebPage class reference in Assistant. Qt says that if you want to create the image of the web page try following code:
@
void CreateImageFromWebPage(QWebPage* page)
{
page->setViewportSize(page->mainFrame()->contentsSize());
QImage image(page->viewportSize(), QImage::Format_ARGB32);
QPainter painter(ℑ);page->mainFrame()->render(&painter;); painter.end(); QImage thumbnail = image.scaled(400, 2000); thumbnail.save("some_image.png");
}@
This works ok for a web-pages with small content. But try something which has a content about 1008X46657 which is actually realistic (e.g. http://www.imdb.com/title/tt0108757/fullcredits). It starts to render and it doesn't finish.... Sometimes it gives a segmentation fault sometimes it just hangs in that way without giving user ability to have input on that widget.
Now I'd like to ask my questions about this issues:
-
How can I make this image created for long web pages? Is there any idea which will work better?
-
I'd like to do this rendering process in background (within another thread) as it is time consuming and I don't want to block my user for using the browser, but Qt yields on me when I call that QWebFrame::Render() method outside of a GUI thread.
-
-
The beauty of open source is this:
I came across "this":http://qt.gitorious.org/qt-labs/graphics-dojo/blobs/master/websnap/websnap.cpp example some time ago, and I re-wrote that part for simplicity and reference purposes here on the forums:
@ m_TargetSize = QSize(400, 300);
QSize size = ui->webView->page()->mainFrame()->contentsSize(); size.setHeight(size.width() * m_TargetSize.height() / m_TargetSize.width()); QImage m_Image = QImage(size, QImage::Format_ARGB32_Premultiplied); m_Image.fill(Qt::transparent); QPainter p(&m_Image); ui->webView->page()->setViewportSize(ui->webView->page()->mainFrame()->contentsSize()); ui->webView->page()->mainFrame()->render(&p); p.end(); m_Image = m_Image.scaled(m_TargetSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); m_Image.save("page_thumbnail.png");@
I hope this helps for the thumbnail part.
Now as for rendering in the background, you have a QThread class which you must derive in your own class and implement run() virtual method such as one below, and apply all the logic there:
@class ImageThumbnailThread : public QThread
{
Q_OBJECT
public:
explicit ImageThumbnailThread(QObject *parent = 0);protected:
void run();};@
But as far as I know, you should play with pixmaps in main thread only, but I'm not quite sure on this.
-
With this example you will not get the whole representation of the page. I want that image will represent the whole web page content (I'm creating a small viewer which represents the content of the web page). With your example the row size.setHeight(size.width() * m_TargetSize.height() / m_TargetSize.width()); makes not available to render the page with whole height.
I'm convenient with QThread, the problem is that QWebFrame::render() method uses QPixmap's in it's implementation and it is not available to move it to other thread. Also that render() method is most time consuming part of the algorithm (no need to create a thread if I will do the time consuming part of the algorithm in the main thread).
-
-To get the full page content, you should use QWebElement::render() on the document element of the mainframe. QWebPage::render() has clipping by the viewport.
-You should use QImage::Format_ARGB32_Premultiplied
-About the crash, not much I can tell without a backtrace. I suggest you to give one here or to open a bug on Bugzilla if you think it is a proper bug.
-About rendering in threads, WebKit is not thread safe. Otherwise specified in the documentation, you should assume a class is not thread safe.