Scale Image in QWidget for printing - qt

I use the following code to print a complex widget with text and static images:
printer = QPrinter()
printer.setResolution(PRINTER_DPI)
painter = QPainter(printer)
painter.scale(SCALE, SCALE)
my_widget.render(painter)
painter.end()
Text looks nice after applying scale() but the pixmaps on the widget still look pixelated when printed. I tried using a higher resolution source image and setting scaledContents on QLabel but this didn't seem to help.
Any ideas how I can increase the image resolution for printing?
Edit: I'm still interested in an answer but in the meantime I worked around the issue by using QSvgWidget with an svg source image instead of QLabel.

Related

Having trouble resizing a QLabel in a QScrollArea

I'm trying to follow the example at the below link to have a picture (in a qlabel) shown in a scrollable area.
https://doc.qt.io/qt-5/qtwidgets-widgets-imageviewer-example.html
I'm using Qt Designer to make the ui instead of hardcoding everything. So I have a QLabel, in a QWidget (with a grid layout assigned to it), in a QScrollArea.
From the tutorial, they state the following for the sizepolicy of the QLabel:
We set imageLabel's [QLabel] size policy to ignored, making the users able to scale the image to whatever size they want when the Fit to Window option is turned on. Otherwise, the default size policy (preferred) will make scroll bars appear when the scroll area becomes smaller than the label's minimum size hint.
Setting it to ignored fits to the window, as expected and as stated. Setting it to preferred provides scroll bars when the image is larger than the scroll area, also as expected and as stated. My issue is that when the sizepolicy is set to preferred, the resize function of the QLabel doesn't work. It always stays at the default size of the loaded image. The only way that I'm able to get the resize function to work is when I don't assign a layout/break the layout to the widget in the QScrollArea, but then no scrollbars will appear when the image is larger than the QScrollArea.
Does anyone have any ideas of how to make the resize function and scrollbars work at the same time?
Thanks in advance for any help. I'm trying to learn qt5 still and this seems like it'd be a simple thing to do, but it's slowly driving me crazy.

How to ensure even pixel size when painting scaled QImage?

I have a 4 channel png image with 8x8 Pixels that is loaded by a QImage. The QImage is then scaled by a factor of 200, so the image will have a new resolution of 1600x1600, each original pixel having a size of 200x200. But when this image is added to a QLabel through the means of a QPixmap and shown on screen, the drawn pixels will have slightly different sizes.
I've taken screenshots with Gimp and looked at the painted image more closely. It seems that every other pixel is slightly bigger than it should be, 201 instead of 200 pixels wide for example. The very last pixel in a row will then be smaller to compensate, so that the entire image has the correct size in the end.
This does not happen for all scaling factors, 100 is fine for example and so are factors that are a power of 2, such as 256.
My original approach was using a QGraphicsView and a QGraphicsPixmapItem in which case I scaled the GraphicsItem instead of the image. The effect was the same.
What effect am I seeing here? And what, if anything, can be done about it?
The code to reproduce this issue is very straightforward
int scale = 200;
image = QImage("some image file");
QPixmap pixmap = QPixmap::fromImage(image.scaled(image.size() * scale));
some_label->setPixmap(pixmap);
Turns out the easiest solution to my problem is to use QOpenGLWidget in the QGraphicsView:
setViewport(new QOpenGLWidget);
This single line in the constructor will result in much higher precision when scaling an image with the caveat of adding OpenGL as a dependency.
Another gotcha with this approach is that calling setViewport invalidates many of the settings done on a QGraphicsView. So if the view is set up in a UI file, as in my case, make sure to call other setters after calling setViewport.
I could not find a better solution that would work without OpenGL, short of writing my own rasterizer of course.

Transparent QGraphicsWebview over QGLWidget leads to super imposed images

I have a transparent QGraphicsWebview inside a QGraphicsView with the following settings:
The QGraphicsView is the high level widget, and is shown in full screen mode
The graphics view uses a QGLWidget as its view port (to use opengl-es)
Alpha channel and double buffering are enabled in this QGLWidget
Transparency is achieved by graphicsView->setStyleSheet("background:transparent")
Following attributes are set for QGraphicsView and QGraphicsWebview
WA_TranslucentBackground = true
WA_NoSystemBackground = true
WA_OpaquePaintEvent = false
The QPalette::Base and QPalette::Window brushes of webview and webview->page() are set to Qt::transparent
At the beginning, the transparency works fine. But as the screen get updated (when I scroll), it looks like the new bitmap is blended on top of the existing one to get a superimposed picture. After about 5-6 screen updates, this blending causes the colors to accumulate and form an opaque rectangle (with a corrupted image). Following images show first, second and final stages of the problem.
How do I tell qt/opengl to stop blending and just draw the new image to the frame buffer?
I tried calling fillRect(boundRect(), Qt::transparent) from overridden Webview::paint and GraphicsView::paintEvent; but it didn't work except for making the updates slower.
I am new to Qt and OpenGl, so I might be missing some basic flags or settings.
I tried all the methods mentioned above. They did not work for me. I then debugged into qtbase code and found that setting the Opacity level make the top browser layer transparent.
this->setOpacity(0.1);
this pointer points to the QGraphicsWebView object.
With this method, the whole front browser contents including background will be transparent. To separate header, paragraph and background and to specify different transparent levels for them, I will have to dig into webkit code a little further to figure out the problem. But for now, setOpacity() did the trick and is good enough for what I am doing.
It turns out the problem is graphicsView->setStyleSheet("background:transparent");. Who would have guessed?!
Yeah, the line that I thought made transparency work was actually causing troubles with transparency. The application works fine without that line (or if you change it to background:none)
In short, steps to get a transparent QGraphicsWebview using QGLWidget:
Set the Base palettes of QGraphicsWebview, QWebpage and the outer QGraphicsView to Qt::transparent
scene->setBackgroundBrush(QBrush(Qt::transparent));
You should also make sure that html body background is set to transparent values:
html, body {
background-color: rgba(127, 127, 0, 0.5);
}

Qt - QTextCursor insertImage low resolution when printing on pdf

I have a QImage and a QPainter that paints on this image. After painting I tried to insert this QImage to QTextDocument with QTextCursor's insertImage method :
QImage image(width ,height,QImage::Format_RGB32);
QPainter paint;
paint.begin(&image);
paint.drawText(25,25,someText);
paint.end();
QTextCursor cursor(doc);
cursor.movePosition(QTextCursor::End);
cursor.insertImage(image);
But after doing this what I got is a text with a low resolution or a line width saggy pixels like in this image :
!(http://imgim.com/4698inciz7774617.png)line image
I tried setting QTextDocument's layout's paint device but it gave an error because of null pointer, this is most probably because of the document does not have a layout
I tried setting render hints of painter but it does not work too.
I inserted some html before the image in the document but they are good in terms of resolution, also there are no problem in flat lines.
When I show this document in a QTextEdit it seems fine, but when this is in a pdf file in a preview or something something goes wrong.
My printer is defined like that in preview :
QPrinter printer(QPrinter::HighResolution);
QPrinter highprinter(QPrinter::ScreenResolution);
printer.setPaperSize(QPrinter::A4);
And I call QTextDocument's print method for printing.
Do you have any solutions for this?
thanks
Saggy pixels can be eliminated somehow with : QPainter::setRenderHint(QPainter::Antialiasing, true); however it seems it does not eliminate saggy pixels in letters very much.
Other way of eliminating saggy pixels fully is creating a document with large pixel sizes (resolution) and increasing size of the image.After that we can increase font point size and line widths it prevents aliasing as I saw in my trials.
//increasing line width when drawing line
paint.setPen(QPen(Qt::gray,20, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
//increasing font's point size when using text
qFont2.setPointSize(100);
paint.setFont(qFont2);
However increasing font point size does not prevent aliasing when the image's pixel size (resolution) remains same

In GWT, is it possible to scale an image widget to smaller than its original size?

I am wondering if it is possible to shrink an image widget down to a size that is smaller than the image resource itself. I have tried the following:
imageResource.setSize(size, size);
imageResource.setPixelSize(size, size);
I have also tried re-sizing in the CSS file. But when I size the image to smaller than the original, it just crops it down and doesn't actually shrink it. It seems to me the solution is to use a high resolution, smaller image that I can scale up if need be, but I feel like I'm missing something here.
You can use CSS3 background-size property to scale the image:
http://www.w3schools.com/cssref/css3_pr_background-size.asp
Note that it's not supported in some very old browsers.
You can also try with,
ImageResorce myImage = new ImageResource();
myImage.getElement().setAttribute("height","20px");
myImage.getElement().setAttribute("width","20px");
cheers !!!

Resources