PDA

View Full Version : QImage inserted into QGraphicsTextItem looks fuzzy, when scaling QGraphicsTextItem



stefan-koch
12th November 2010, 17:36
Hello,

Look into the attachment: screenshot.png

There is a problem with the "asdf" (QImage) in the QGraphicsTextItem: it is fuzzy. And that's because the QGraphicsTextItem is scaled with setScale(...).

I scale the QGraphicTextItem, because I want zoom the text in/out later in the programm. And yet I zoom it because the text should have the correct size in millimeters.

The text scaling works fine, but the "asdf" QImage will zoomed, too.

How to insert a QImage with high resolution, and make it smaller with scaling that the QImage doesn't looks fuzzy?
Or there other ways to solve this?

(An idea is to get the HTML of the TextItem and multiplicate all font sizes with the zoom level. But is there a better way?)

Thanks

Stefan Koch

high_flyer
15th November 2010, 15:19
How to insert a QImage with high resolution, and make it smaller with scaling that the QImage doesn't looks fuzzy?
Just the same as you did, just make the QImage size larger, and scale it to the result size you need.

But why don't you use QGraphicsTextItem?

stefan-koch
16th November 2010, 12:17
I don't understand your question:

But why don't you use QGraphicsTextItem?

I use QGraphicsTextItem.


... make the QImage size larger, and scale it to the result size you need.
How make a QImage size larger? Or: How to scale a QImage?

In my situation I set the scale of the QGraphicsTextItem a. e. to 1.5 (I make it greater, not smaller)

Thanks

high_flyer
16th November 2010, 12:26
I use QGraphicsTextItem.
But you are using QImage for the 'asd' text as well - why?
I guess I don't understand what it is you are trying to do...


How make a QImage size larger?
QImage ( const QSize & size, Format format )
QImage ( int width, int height, Format format )
QImage scaled(...)

stefan-koch
16th November 2010, 13:28
I have tested now, insert a scaledToHeight() image into the QGraphicsTextItem, the image is now smaller, but always the same rendering problem.

I have a QGraphicsTextItem with setScale it will be scaled.
see setScale(x)
if x<1
it works
if x>1
the inserted image get's fuzzy, it will be automatically zoomed, without enough information, a. e. the image is 15x15 pixel, now it will be automatically zommed by QT to 20x20 but the informations are only in 15x15, so QT must interpolate. Is is it possible to insert a Image with 150x150 pixel and zoom it to 10% that are enought informations here, and that's no interpolating needed if scale the QGraphicsTextItem to 1.5 (something higher as 1) - that's my idea of the problem - this idea could wrong


P. S. : I insert the image with a QTextCursor (cursor->insertImage(...))

high_flyer
16th November 2010, 14:36
I still fail to understand why you are using a QImage... what is it for?
Why not just let QGarphicsTextItem do the text rendering?
It will scale it correctly too!

Be as it may to your question:

Is is it possible to insert a Image with 150x150 pixel and zoom it to 10%
Yes as I said before, I probably just don't understand again - where is the problem?
Create the QImage 150x150 and scale it down to 15x15... You know how to create QImage which is 150x150, and you know how to scale it... so I don't see where is the problem?

stefan-koch
16th November 2010, 16:51
Why not just let QGarphicsTextItem do the text rendering?
I have added a new screenshot to this answer, I hope this screenshot says all.
(Or is QGraphicsTextItem able to render LaTex?)

The third small image is the scaledToHeight(10) Image, it's fuzzy too.

The original sqrt-Image the alonestanding sqrt-png-file.

Added after 8 minutes:

The unscaled QGraphicsTextItem is also attached as png-File (here is a red Text included, that says that this is unscaled)

high_flyer
16th November 2010, 17:21
I see.
Try turning anti aliasing off if its on and see if it helps.


(Or is QGraphicsTextItem able to render LaTex?)
QGraphicsTextItem probably doesn't render LaTex, but you might find this interesting:
http://doc.trolltech.com/solutions/4/qtmmlwidget/

stefan-koch
18th November 2010, 08:42
Hello,

now I have disabled setRenderHint(QPainter::SmoothPixmapTransform) in QGraphicsView.
Antialiasing is not enabled in QGraphicsView.

See screenshot for details.

What's the problem?

Thanks

high_flyer
18th November 2010, 10:00
Hmm... I think this is just a scaling artifact. You don't see that with the text object (probably) because it really does render the text when scaled - and probably the line width is not as thin as it should be but a width that looks good at that size , but your QImage is just scaling it, making the lines thiner and when they are near each other you see the difference.
But that is just a guess.

stefan-koch
18th November 2010, 10:58
What mean you with "lines"?

wysota
18th November 2010, 10:59
Did you enable smooth image transformations for your view?

stefan-koch
18th November 2010, 11:44
@wysota
Do you mean this: setRenderHint(QPainter::SmoothPixmapTransform)
it was enabled in QGraphicsView in post #7 (see screenshot for details)

wysota
18th November 2010, 13:13
In general your image is of a very poor quality. The Nyquist law is merciless here.

stefan-koch
18th November 2010, 17:35
So it does not work at all.
I have made a little test project. A MainWindow with a GraphicsView. I add the source code, if you want you can test it on your own computer (unzip the attachment TextItemTest.zip and compile it).

Note the attachment tex.png must be saved in your home folder (/home/<USER> on Linux).

And the third attachment shows you the screenshot of the little text project, including fuzzy sqrt-5 image NOW with 3600 dpi! (scaled to height 30 pix)

Thanks

A little code cutting form the test project:

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QDir dir;
dir.cd(QDir::homePath());

//ui->graphicsView->setRenderHint(QPainter::SmoothPixmapTransform);
//ui->graphicsView->setRenderHint(QPainter::Antialiasing);

QGraphicsScene *scene = new QGraphicsScene;
ui->graphicsView->setScene(scene);

QGraphicsTextItem *textItem = new QGraphicsTextItem;
textItem->setTextInteractionFlags(Qt::TextEditorInteraction) ;
textItem->setPlainText("test");

QImage image(dir.absoluteFilePath("tex.png"));
QImage imageScaled = image.scaledToHeight(30, Qt::SmoothTransformation);
//QImage imageScaled = image.scaledToHeight(30);

textItem->textCursor().insertImage(imageScaled);

textItem->setScale(3);

ui->graphicsView->scene()->addItem(textItem);
}

P. S. set scale to 1 instead of 3 and it works fine
How is it possible to reply in a new post not by editing my old post (if nobody answered first)????

high_flyer
18th November 2010, 20:54
Wait a minute...


textItem->textCursor().insertImage(imageScaled);

textItem->setScale(3);

No wonder you get poor quality!
You put your DOWN scaled image, and scale it up x3 !!
You should do it so:


QImage image(dir.absoluteFilePath("tex.png"));
QImage imageScaled = image.scaledToHeight(30, Qt::SmoothTransformation);

textItem->setScale(3);

textItem->textCursor().insertImage(imageScaled);

You have to scale DOWN your LARGE image not UP the SMALL image!

stefan-koch
18th November 2010, 22:08
Is the only change to my code to swap the lines 23. and 25. from post #15?

I can't see any change in your code improvement, as that you have swapped these lines, right?

Now the new code, with exactly the same issue:

What went wrong?

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QDir dir;
dir.cd(QDir::homePath());

//ui->graphicsView->setRenderHint(QPainter::SmoothPixmapTransform);
//ui->graphicsView->setRenderHint(QPainter::Antialiasing);

QGraphicsScene *scene = new QGraphicsScene;
ui->graphicsView->setScene(scene);

QGraphicsTextItem *textItem = new QGraphicsTextItem;
textItem->setTextInteractionFlags(Qt::TextEditorInteraction) ;
textItem->setPlainText("test");

QImage image(dir.absoluteFilePath("tex.png"));
QImage imageScaled = image.scaledToHeight(30, Qt::SmoothTransformation);
//QImage imageScaled = image.scaledToHeight(30);

textItem->setScale(3);

textItem->textCursor().insertImage(imageScaled);

ui->graphicsView->scene()->addItem(textItem);
}

high_flyer
19th November 2010, 09:34
Hmm... I don't know.

If you take your original large image, and scale it to 30 in an image editing application, does it look the same as the one you get with your code?

stefan-koch
19th November 2010, 11:27
Yes, exactly.

See screenshot in this thread (test1.png).

I add the source code of the project (all headers, all cpps, ui-file, ...) this will be found in the TextItemTest.zip attachment of this thread. If you want you can test it on your own pc.

I add the tex.png, the 3600 dpi sqrt-5 file, too (to this thread).

Thanks.

high_flyer
19th November 2010, 11:44
Yes, exactly.
What yes exactly?
The image the edit application gets is the same results as your scaling in the application?

stefan-koch
19th November 2010, 12:22
What mean you with?:
The image the edit application gets is the same results as your scaling in the application?

Have you compared screenshots in post #15 and #19?

high_flyer
19th November 2010, 12:41
I lost you completely.

I suggested you try to scale the image with a graphics editing application the same way you do in your application to see if the result is the same.
If it is, then there is little you can do, probably you will have to scale to not so small size.
If the graphics editing application has a better visual result after scaling, then I don't know what the cause for the blur in the scaled image is.

wysota
19th November 2010, 12:44
test1.png is obviously scaled up, it is not 30px in height. Show us the result of scaling the image to 30px.

stefan-koch
19th November 2010, 13:14
look at post #17's code.

If I change the line
textItem->setScale(3);
to
textItem->setScale(1);

I get the following attached screenshot (test2.png). The images is now of good quality and should have 30 pix in height.

@high_flyer
scaled in a Graphics Editing Application (scaled image is tex.png - 3600 dpi - attached):
unscaled: graphicseditingapplication1.png
scaled smaller: graphicseditingapplication2.png
scaled up: graphicseditingapplication3.png

wysota
19th November 2010, 13:36
look at post #17's code.

If I change the line
textItem->setScale(3);
to
textItem->setScale(1);

I get the following attached screenshot (test2.png). The images is now of good quality and should have 30 pix in height.
That's exactly what I would expect. And if you scale it 3 times up it will be distorted. Are you expecting anything different?

You are aware that if you scale down an image 3 times and then scale it up three times you will not get the original image, right?

stefan-koch
19th November 2010, 13:49
That's exactly what I would expect. And if you scale it 3 times ...

That's the problem. How to solve it?
Look at OpenOffice if I insert a picture and zoom over 100 % in my example to 256% the picture looks good. (Note: I have maked the picture smaller in openoffice first - pick one edge with the mouse and move the mouse to make the image smaller)

see openoffice1.png (100% scaled), and openoffice2.png(256% scaled) for details.

My goal is to create a big image (example tex.png with 3600 dpi) and insert this scaled (smaller) into a QGraphicsTextItem, and scale the QGraphicsTextItem up and now QT should be intelligent, and knowledge about the big image (it should have the big image after scaling smaller) and now if I scale the QGraphicsTextItem up, I want that QT does automaticaly see that the QImage has a parent that is bigger and use the information of this, not use the information of the small scaled image.

high_flyer
19th November 2010, 13:58
That's the problem. How to solve it?
'That' (again one needs to guess what you mean) is not the problem.
The problem is the way you expect the scaling to work for you.

What open office does (probably) is show you scaled version of the original image each time, not a scaled version of the scaled image.
You need to do the same (that is how you solve it, what we are trying to explain to you in last 5-6 posts).
You need to have a living copy of the original image at hand, and scale it only down (from big to small), and not up (from small to big).
When you want to scale the small image up, you don't scale it really, you scale the original large image to the new scale factor you want the small image scaled up to.
When you scale - you always should scale the original image, not a scaled copy.


and scale the QGraphicsTextItem up and now QT should be intelligent, and knowledge about the big image
Qt is not "intelligent".
And its not Qt that has your image information, but a QImage object.
YOU have to supply the intelligence in your code, to use it.

stefan-koch
19th November 2010, 14:07
Yes now I have understand the problem. Thanks.

But how to forbid QT (QGraphicsTextItem) to automatically scale up the inserted (small) image?

Thanks

wysota
19th November 2010, 14:26
But how to forbid QT (QGraphicsTextItem) to automatically scale up the inserted (small) image?
Qt doesn't scale things up on its own. If it scales something up it is only because you tell it to. If you expect an image to be scaled up then put in a big image and scale down the item containing it. Then when the item is scaled up again, it will still use your original (non-scaled) image to calculate the result.

stefan-koch
19th November 2010, 14:45
Means that first scale up the QGraphicsTextItem and then insert the scaled image?


Qt doesn't scale things up on its own. If it scales something up it is only because you tell it to.
How did I this? Is it this line?: textItem->setScale(3);

wysota
19th November 2010, 14:54
Means that first scale up the QGraphicsTextItem and then insert the scaled image?
No. Put the original image, don't scale it yourself.


How did I this? Is it this line?: textItem->setScale(3);
This scales up, not down.

stefan-koch
19th November 2010, 14:58
This scales up, not down.
You mean that?: textItem->setScale(0.2);

What's with the text inside of the TextItem?

stefan-koch
19th November 2010, 22:07
Thank you high_flyer and wysota for your numerous present answers!

Note: The text and image inside of the QGraphicsTextItem should be independend of each other when scaling.

Is this possible with standard methods? Or is complex code needed? If yes, where to start?
Thanks.

wysota
20th November 2010, 01:30
It depends what you really mean by "independant". If they are really to be independant then they should not be the same item.

stefan-koch
20th November 2010, 11:49
independend should mean:
- the text and image is in one QGraphicsTextItem (not the text in a QGraphicsTextItem and the image in a QGraphicsPixmapItem)
- the image is sepaeratley scalable from the text, just both are in the same item

See screenshots snapshot1.png and snapshot2.png as example with openoffice

snapshot1.png shows you the image in openoffice inserted into the text ("As Character")
I think this is like a QGraphicsTextItem with a inserted QImage
snapshot2.png shows you the image in openoffice fixed to the page ("To Page")
I think this is like a QGraphicsPixmapItem fixed to the QGraphicsView and text in a QGraphicsTextItem (or anything outside of QGraphics... classes)

In my case the image should be fixed to the text. And the image should be zoomable.
Is this possible?

wysota
20th November 2010, 16:09
Your examples from open office probably treat the picture and the text as two separate items that are groupped together within a third item. You can follow the same pattern here. To be honest I don't see your problem. Open Office doesn't scale down your image anywhere, it operates on the original image everywhere and that's what you should do too.

stefan-koch
20th November 2010, 17:35
Hmm, can I do that with one item or need I three, too?
How would you proceed? Working again with QGraphicsTextItem or with QGraphicsItem, or with ...?

Look into attached screenshot.

wysota
20th November 2010, 17:57
I don't even know what you are doing :) I probably wouldn't use Graphics View here at all, I don't see any benefits.

stefan-koch
20th November 2010, 18:04
But if I use QGraphicsView, there is a problem

See last openoffice screenshot
teIMAGEst
What is if the user want edit the "te" before the IMAGE?
Would GraphicsView automatically set a new position for the IMAGE?

wysota
20th November 2010, 18:09
Why aren't you simply using QTextDocument with your own document layout (if needed)?

stefan-koch
20th November 2010, 18:19
In a QTextDocument I can insert images, too. Can I set rules what happens at QGrpahicsTextItem scaling with the QAbstractTextDocumentLayout (as example: no scaling of images, when scaling the TextItem)?
Or there are the same issues?

----

Another question: you have a DIN A4 page in OpenOffice with text cursor, what could that be in QT a QGraphicsTextItem (or is this more a TextField in OpenOffice)?

wysota
20th November 2010, 18:23
You can't set any "rules", you can only implement your own text layout. it is solely the layout's decision how it renders the document.

stefan-koch
20th November 2010, 18:25
And then the "image is fuzzy" problem will be solved?

wysota
20th November 2010, 18:37
I have no idea, I don't even know what you are doing. I have a feint feeling you are trying to do something with a really bad approach.

stefan-koch
20th November 2010, 18:59
Now I will show what I'm doing...

See screenshot for details, there I have commented my idea.
(the handwritten text are multiple QGraphicsItem's, they have their own class GraphicsItem that including a QVector of QPointF's, and a painting method that draws the lines)

My program should be a alternative to Xournal, but with the feature to insert Math. Formulas...

wysota
20th November 2010, 19:10
Look, if you insert an image into a text item, you insert a bitmap of specified dimensions. If you start scaling this item, the bitmap gets scaled too. If you scale the item up, the image will be scaled up as well and once its size starts getting larger than the size of the image inserted into the item, you'll start getting artifacts. If you operate on a static bitmap there is no workaround for that. If you use the image insertion variant that uses a QTextImageFormat either the default layout will try to generate proper bitmaps for you or you will be able to implement a custom text layout engine that will generate proper bitmaps depending on the area the whole document is to occupy. But still if the image source provides a bitmap smaller than the requested size, you'll be getting artifacts. Open Office probably generates an outline (vector) and not a bitmap so it can easily cope with this situation. If you are able to generate outlines (like (e)ps) for your math formulas, it will be trivial to solve the problem of a finite resolution of the bitmap.

stefan-koch
20th November 2010, 19:34
If you are able to generate outlines (like (e)ps) for your math formulas, it will be trivial to solve the problem of a finite resolution of the bitmap.

I'm able to get a SVG of the formula, or PS could work, too.

But I'm think about, to replace LaTeX support to MathML support (http://doc.trolltech.com/solutions/4/qtmmlwidget/ , high_flyer made me watchful about the qtmmlwidget)

But qtmmlwidget is a widget, what's to do with that (have QGraphicsImageItem a inputWidget() method - I'm not aware that there is one)?

But all in all, the possibility to insert a png or jpeg image must given, it should possible to insert generic pictures (not formulas). And not of all pictures exist's a svg...


(like (e)ps) for your math formulas, it will be trivial to solve the problem
Why is that so trivial?

wysota
20th November 2010, 20:55
But I'm think about, to replace LaTeX support to MathML support (http://doc.trolltech.com/solutions/4/qtmmlwidget/ , high_flyer made me watchful about the qtmmlwidget)
If you do that, you make your application dependent on Internet and availability of some webservice.


Why is that so trivial?
Because vectors are mathematical entities, they don't have a resolution.

stefan-koch
22nd November 2010, 10:31
Because vectors are mathematical entities, they don't have a resolution.
How to insert SVG's or (E)PS in a QGraphicsTextItem?

http://doc.trolltech.com/4.7/richtext-textobject.html
With this example we get again a QImage...

How look's the trivial solution with SVG, EPS?

wysota
22nd November 2010, 15:49
Read my lips: there is no single function call you can make to obtain the goal you want. You'll have to get your hands dirty. The example you posted is a good start.

stefan-koch
26th November 2010, 14:06
So it works with QTextImageFormat


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QDir dir;
dir.cd(QDir::homePath());

ui->graphicsView->setRenderHint(QPainter::SmoothPixmapTransform);
ui->graphicsView->setRenderHint(QPainter::Antialiasing);

QGraphicsScene *scene = new QGraphicsScene;
ui->graphicsView->setScene(scene);

QGraphicsTextItem *textItem = new QGraphicsTextItem;
textItem->setTextInteractionFlags(Qt::TextEditorInteraction) ;
textItem->setPlainText("test");

QImage *image = new QImage(dir.absoluteFilePath("tex.png"));

QTextDocument *document = textItem->document();
document->addResource(QTextDocument::ImageResource,QUrl::fro mLocalFile(dir.absoluteFilePath("tex.png")),*image);

QTextImageFormat imageFormat;
imageFormat.setName(dir.absoluteFilePath("tex.png"));
imageFormat.setHeight(30);

textItem->setScale(4);

textItem->textCursor().insertImage(imageFormat);

ui->graphicsView->scene()->addItem(textItem);
}

The project is attached in the zip-file.
The attached screenshot show you the result.

NOTE: You see two windows in the (one) screenshot.

Left you see setScale(1) and right setScale(4)

But in setScale(1) the rendering is not as good as with image.scaledToHeight(30, Qt::SmoothTransformation);

After setting setScale(4) it is better than with image.scaledToHeight(30, Qt::SmoothTransformation); but without scaling it's not so good.

I think SmoothTransformation is not enabled in this case.

How to enable it?

wysota
26th November 2010, 14:24
QTextObjectInterface::draw() might be responsible for scaling the image.