Text rendered as blobs on mono images in qt5 - image

I am trying to "print" items that contain text, onto a mono image.
I have items that either subclass QGraphicsTextItem, or some other class that uses painter->drawText().
I can do it in Qt4 - but in Qt5, all I get are some blobs. I have tried to experiment with a small sample program, but I can't figure out what is going on...
Here is a simple self contained program:
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsTextItem>
class TextItem : public QGraphicsItem
{
public:
TextItem(){}
virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget* = NULL)
{
QPen p(Qt::red);
painter->setPen(p);
painter->setBrush(Qt::NoBrush);
//painter->setFont(QFont("Arial", 30));
painter->drawText(boundingRect(), Qt::AlignCenter, "abcd");
}
virtual QRectF boundingRect() const { return QRectF(0, 0, 30, 20); }
};
void processScene(QGraphicsScene* s) {
QGraphicsTextItem* t = new QGraphicsTextItem();
t->setPlainText("abcd");
// t->setDefaultTextColor(Qt::red); // won't make a difference
t->setPos(0, 0);
s->addItem(t);
//t->setFont(QFont("Arial", 30));
//t->setTransform(t->transform().fromScale(3,3));
TextItem* t1 = new TextItem();
t1->setPos(0, 20);
s->addItem(t1);
QImage image = QImage(s->sceneRect().size().toSize(),
QImage::Format_Mono);
//QImage::Format_RGB32); // this works in qt5
image.fill(QColor(Qt::color0).rgb());
QPainter painter;
painter.begin(&image);
s->render(&painter);
painter.end();
image.save(QString("../test.bmp"));
}
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QGraphicsScene s;
s.setSceneRect(0, 0, 50, 50);
QGraphicsView view(&s);
view.show();
processScene(&s);
return app.exec();
}
Running it in Qt4 it gives what is expected: outputs a mono image containing text (in both versions, using QGraphicsTextItem or paint->drawText() (left image).
The same in Qt5 only shows some blobs in place of text (right image):
I have tried all kinds of experiments... Setting the font doesn't make a difference (except, for QGraphicsTextItem, setting the font to something big AND scaling to something big - but that is not useful in a practical application).
The other thing that worked in Qt5 is rendering to a color image instead of mono - but that is very bad for my application, where I need to store small mono images. My thought would be then, for Qt5, to render text to a color bitmap and then convert it to mono... But really !
I have also tried to save the items themselves to a bitmap, in a function implemented inside their class - it did the same thing.
I have tried to set point size on the QFont before applying it.
Is there something else I can set on QPainter in order to draw text ?
I found a related question: QT5 Text rendering issue also asked again in Qt forums: QT5 Text rendering issue. But that question refers to all rendering, and to a Qt5 in Alpha on a MIPS based platform... It implies that other platforms don't see that issue...
I'm using 5.5.0... I am also running under windows... And rendering on color image works... And...
I simply do not understand the "solution":
For time being, when we tried forcefully to enable Glyph cache, then
we are not seeing this issue.
Not sure what that means and how to do it.
Why is text painting blobs on mono images (but fine on color images) in qt5 and what can I do to fix it ?
Using Qt 5.5.0 32 bit, in Windows 7
Edit:
1) I tested the code in 5.4.2 and it renders text correctly.
I tried to compare some of the relevant code in qpainter.cpp, qtextlayout.cpp, qpaintengine_raster.cpp, qtextengine.cpp
- but with my limited understanding, the changes between Qt 5.4.2 and Qt 5.5.0 look logical... and would not affect the behavior...
2) I did paint my text on a color QImage, then painted it on mono - it worked fine on my own text items, but a third party software that creates very small text gives me very bad resolution when I try the same (illegible).

Related

QPixmap empty when loading it from an image

I have an app that loads an image in a QPixmap, which changes depending on the user's request.
Not all images have the same format, or the same size, some vertical and others horizontal.
I am using Qt5.14.2, with MinGW 7.3.0 32-bit and Qt Creator 4.11.1. in W10.
On a machine running W8.1 and the same version of Qt, MinGW and QtCreator have been working fine.
The first image loads perfectly, but if I change it, it already returns the empty QPixmap.
I have done different tests to be able to load the image, resizing the QPixmap (with fixed dimensions and with those of the image),
saving the QImage to a file and loading it from the file putting the PNG format, etc.
I have been able to check that the images are generated correctly, to rule out that it would be a problem when converting the data to QImage.
Any idea what is happening? I can't put the code because it's quite an extensive app, so I'll narrow it down to where the problem is
My_class.h:
QPixmap pixmap;
My_class.cpp:
int w=num_celdas_imagen_x*128;
int h=num_celdas_imagen_y*128;
unsigned char *data =(unsigned char *)malloc(w*h*3);
// filling data
QImage img = QImage((unsigned char *)data,w,h,QImage::Format_RGB888);
// At this point I have been able to check that the image is generated correctly
this->pixmap = QPixmap::fromImage(img);
// At this point the QPixmap is null (except with the first image, which loads fine)
Thanks

How to properly position a QGraphicsTextItem on a QGraphicsScene

The probelm I have is that I am trying to position a QGraphicsTextItem on a specific location of my QGraphicsScene , to be precise in the center of the speedometer below. But nothing I tried seems to work properly. Despite I clearly provided the coordinates I want the QGraphicsTextItem, it still anchored on top-left as shown below:
Below the snippet of code:
speedwidget.cpp
SpeedWidget::SpeedWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::SpeedWidget)
{
ui->setupUi(this);
mScene = new Scene(this);
ui->graphicsView->setScene(mScene);
io = new QGraphicsTextItem;
io->setPos(210,240);
QFont *f = new QFont;
f->setPointSize(18);
io->setFont(*f);
mScene->addText("Odometer :")->setDefaultTextColor(Qt::red);
mScene->addItem(io);
}
speedwidget.h
class SpeedWidget : public QWidget
{
Q_OBJECT
public:
SpeedWidget(QWidget *parent = nullptr);
~SpeedWidget();
private:
Ui::SpeedWidget *ui;
Scene *mScene;
QGraphicsTextItem *io;
};
#endif // SPEEDWIDGET_H
What I tried so far to solve the problem was:
I consulted this post which explained the idea but I don't need to change the background color in this example.
This one had a good snippet, but I am not trying to highlight the color. I am only trying to position the text on a specific location.
If I change io->setPos(210,240); and give different numbers, I still see it anchored on top-left.
Thanks for pointing to the right direction for solving this issue.
The Qt Graphics View framework implements a parent-child mechanism. Simply make your QGraphicsTextItem become a child of your odometer's dial item. From then on, your text label's position will be relative to the one of the dial:
io = new QGraphicsTextItem(this);
// Position text item so that it's centered on the dial
...
Furthermore, note that this line:
mScene->addText("Odometer :")->setDefaultTextColor(Qt::red);
Means that you create yet another text item. A pointer to the newly created item is being returned. Either use & retain that one or use the one that you explicitly created with the new expression.
Furthermore you might want to reconsider your choice of using a QGraphicsScene for one simple "widget". While the Qt graphics framework is not necessarily heavy, it certainly brings quite a lot of overhead for just rendering an odometer.
You can simply overwrite the QWidget::paint() function in your SpeedWidget subclass and render everything using QPainter. That will be a lot lighter and also a lot less hassle.

Can i use QPainter/QPaintDevice for a existing native Window of a non Qt Application?

I maintain a large Win32 application and i'd like to migrate some parts of it to Qt (currently using 4.8). The first part would be to transform rendering of images and shapes to Qt. The core of the application is quite huge and can not be transformed as a whole.
I managed to compile and link using QImage.
I can start the application and load a image into the QImage object.
Then i tried to create a QWidget from my existing Win32 Window using the following code:
class MyWidget : public QWidget
{
public:
void create(HWND hwnd)
{
QWidget::create(hwnd);
}
};
This was necessary, as create is a protected member of QWidget (yes i now my approach is a little bit thoughtless...).
Then i tried:
qWin.create(hwnd);
QRect rect(...);
qWin.paintEngine()->drawImage(myImage.rect(), myImage, rect);
This asserts in QWidgetPrivate::QWidgetPrivate with
qFatal("QWidget: Must construct a QApplication before a
QPaintDevice");
Is there any way to do this?
Can i somehow us a QPainter or QPaintDevice for a existing native Window of a non Qt Application?

Is there any way to draw a PNG image on window without using MFC?

I am developing a Windows API application without using MFC.
I am using standard Windows libraries.
How do I draw a PNG image in a window?
Help me with some sample code.
I have tried some codes which are available on the Internet, but all are using MFC.
Take a look at this StackOverflow question. It offers several options which should meet your needs.
Adapted from MSDN:
#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
using namespace Gdiplus;
void draw()
{
// start up GDI+ -- only need to do this once per process at startup
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
Rect rect(20,20,50,50);
Graphics grpx(dc);
Image* image = new Image(L"SomePhoto.png");
grpx.DrawImage(Img,rect);
delete image;
// shut down - only once per process
GdiplusShutdown(gdiplusToken);
return;
}
Your choices are: GDI+, WIC(Windows Imaging Component) or libpng
You can use GDI+. See Loading and Displaying Bitmaps.
The below code worked for me. It's free of MFC and can be used straight away to draw PNG images in a window.
Gdiplus::Image image(L"C:\\Logo.png") ;
Gdiplus::Graphics* graphics = Gdiplus::Graphics::FromHDC(GetDC(hWnd));
RectF ImgRect(0,0,y3/10,y3/10) ;
Gdiplus::Status result = graphics->DrawImage(&image, ImgRect);
Thanks for all your support and quick response to solve my problem.
If you know PNG'coding,you can decoding it. So you can draw PNG in any way~

Problem in displaying sequence of DICOM images using QT

i'm working in Linux [GCC Compiler] ,
i'm using Eclipse with CDT + QT to compile
I need to display sequence of DICOM images using QT window and OpenGL functions
pls let me know which is the function to display sequence of images
i'm using 3 functions
1) initiallizeGL() to initallize OpenGL functions.
2) resizeGL() instead of glutInitWindowSize() in Glut.
3) paintGL() instead of glutDisplayFunc() in Glut.
4) updateGL() instead of glutPostRedisplay() in Glut.
also pls let me know which are the Glut equivalent functions in QT
glutMainLoop();
glutSwapBuffers();
glutInitDisplayMode();
glutIdleFunc(idle);
glutInit(&argc, argv);
You should be able to easily display images by simply using QGLWidget as your painting device which - depending on your specific usecase - might simplify your implementation. This will draw the image using the OpenGL paint engine in Qt. Something like the following should allow you to display an image;
class CustomWidget : public QGLWidget
{
public:
CustomWidget(QWidget* parent=0) : QGLWidget(parent), pix("foo.jpg")
{
}
protected:
void paintEvent(QPaintEvent *pe)
{
QPainter p(this);
// maybe update the pixmap
p.drawPixmap(this->rect(),pix);
}
private:
QPixmap pix;
};
If you need to put it in a 3D scene, you probably need to load the image as a texture. Some of the Qt OpenGL demos should be able to give you a starting point, e.g. the 'Boxes' demo;
http://doc.trolltech.com/4.6-snapshot/demos-boxes.html
I'd say Qt already take care of gluSwapBuffers, glutInitDisplayMode and glutInit, so you dont need those.
I am also not sure if your mapping of functions is correct, simply put, Qt and Glut think about GL in a different way so possibly you have to to the same (think in a different way) and Qt methods are pretty much self explanatory.
I'd recommend download the code of KGLEngine or any other Qt +GL project to better understand how it works.

Resources