Solved QWebView: strange problem with embedded images
-
Hi there!
I'm faced by very strange problem. I need to convert generated HTML-code into image. For that I use such code:
@QPixmap img(imgWidth, imgHeight);
QPainter painter(&img);
painter.fillRect(img.rect(), Qt::white);
QBrush br(Qt::white);
QPen pn(Qt::black);
painter.setBackground(br);
painter.setPen(pn);QWebView webView;
webView.setGeometry(0, 0, imgWidth, imgHeight);webView.setHtml(content); // content - is given HTML-code
webView.page()->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
webView.page()->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);webView.page()->mainFrame()->render(&painter);@
And it works fine ...but. This HTML-code contains such content:
@<img src="data:image/png;base64, ..." />@
and this image is not displayed. For debugging reasons I created a window with QLabel and QWebView. QLabel is used to show pixmap, generated by the code, presented above. QWebView displays the content, used to generate the image. In other words, I use this window to compare the image, generated by my code, and the representation of the same HTML code by QWebView widget. I use two different buttons to update the pixmap in QLabel and to set the content in QWebView widget.
I found out very strange thing. When I press the first button, QLabel displays the correct pixmap, but without embedded image. When I press the second button, QWebView displays the correct result with embedded image. If after that I press the first button again, the QLabel widget displays the pixmap with enbedded image.
In other words, QLabel displays correct pixmap with embedded image only if QWebView already displays the same content. It seems, QWebView activates something, what allows QWebView, used in my code (see above), to display the embedded image.
Any ideas?
Thank you in advance.
P.S. I use Qt v4.7.4.
Windows 7 x64
MinGW 4.4.0 -
I see the same behavior in Qt v4.8.5.
-
I examined the sources of WebKit and it seems WebKit really ignores the images if the area, where they are located, is invisible currently. And it seems it's necessary to remove this line:
@greaterThan(QT_MINOR_VERSION, 5):DEFINES += WTF_USE_ACCELERATED_COMPOSITING@
from qt-everywhere-opensource-src-4.7.4\src\3rdparty\javascriptcore\WebKit.pri file and recompile Qt to avoid this hm... feature. I'll try it and inform about the results.
-
OK, I've found the solution. The problem was caused by asynchronous loading of content into QWebFrame object. Thus when 'render' method is called in my code above, the image was not loaded yet in spite of the fact, that its content was provided in the 'content' variable.
I fixed it by this way:
@QPixmap img(imgWidth, imgHeight);
QPainter painter(&img);
painter.fillRect(img.rect(), Qt::white);
QBrush br(Qt::white);
QPen pn(Qt::black);
painter.setBackground(br);
painter.setPen(pn);QWebView webView;
webView.setGeometry(0, 0, imgWidth, imgHeight);webView.page()->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
webView.page()->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);QEventLoop loop;
QObject::connect(&webView, SIGNAL(loadFinished(bool)), &loop, SLOT(quit()));
webView.setHtml(content); // content - is given HTML-code
loop.exec();webView.page()->mainFrame()->render(&painter);@
Thanks to all ;)
-
Thanks a lot for this solution. That's code from my project. It generate 1 bit depth monochrome bitmap from html. Maybe someone will help too.
QWebPage page; page.mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); page.mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); page.setViewportSize(QSize(pageWidth, pageHeight)); auto frame = page.mainFrame(); QEventLoop loop; QObject::connect(&page, SIGNAL(loadFinished(bool)), &loop, SLOT(quit())); frame->setHtml(htmlData, QUrl()); loop.exec(); QImage img(QSize(pageWidth, pageHeight),QImage::Format_Mono); QPainter p(&img); frame->render(&p); p.end(); img.save("output.bmp","BMP");