I would like to print/save the QGraphicsScene
in Mono format. I made the scene contain only a single color object (in one of the windows, it actually is black and white).
OutputView::OutputView(QWidget *parent)
: QGraphicsView(parent) {...}
void OutputView::saveToImage()
{
QImage image(scene()->sceneRect().size().toSize(), QImage::Format_Mono);
image.fill(Qt::transparent);
QPainter painter(&image);
painter.setRenderHint(QPainter::Antialiasing); // seems to do nothing
render(&painter);
image.save("output.png");
painter.end();
// to test rgb, i am adding that - but I really need only mono
// I don't know why the background is black, but since I don't intend to use the color version, it is not relevant
QImage image1(scene()->sceneRect().size().toSize(), QImage::Format_RGB32);
image1.fill(Qt::transparent);
QPainter painter1(&image1);
render(&painter1);
image1.save("output1.png");
painter1.end();
}
The quality of the black-and-white image is very poor !
I expected red pixels to become black, but only some of them did. For the 4th pane, I expected all the black pixels to be placed as black in the mono output, but again, only some of them did.
Is there any way to make a black-and-white image with black pixels where the object has color, and white elsewhere ?
I can easily change the code that generates the color sections, to output black instead of the original color, but that doesn't seem to solve the problem (the 4th panel has black color, but the mono image doesn't contain all the pixels).
I need mono because of the memory cost...
How can I make the scenes output correctly into QImage ?
Update1: I even tried to dither the color image - the result was scary (too light in areas that should be darker, weird artifacts, plus I am adding an extra step that is time consuming, and worst of all, adding a very large rgb image... which is exactly what i am trying to avoid, I need monochrome image because of very limited resources)
QImage image(scene()->sceneRect().size().toSize(), QImage::Format_RGB32);
image.fill(Qt::transparent);
QPainter painter(&image);
painter.setRenderHint(QPainter::Antialiasing); // seems to do nothing
render(&painter);
painter.end();
QImage image11 = image.convertToFormat(QImage::Format_Mono,
Qt::MonoOnly | Qt::DiffuseDither);
image1.save("output.png");
Playing with the built-in qt dither methods, I see that the rendering to mono image uses Qt::ThresholdDither
.
If at least I could apply a different dither to the rendering, in a single step, without having to first build a color image and then dither to a new monochrome image, would be a huge improvement. Memory and time are both very important.
Though perhaps what I really need is a fast way to go through every pixel and set it to 1 if its intensity is above .5 and to 0 if below ? That would still mean a separate step after creating the rgb32 image though... and for some reason doing it "by hand" is always slower than the built-in methods.
Update2: the item painted in this example is a rectangle with a gradient brush. I also separated colors into the 4 QGraphicsScenes: if color == color1 then color2,3,4 = Qt::white and so on.
void Item::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/)
{
QRadialGradient radialGradient(0, 0, 300, 100, 100);
radialGradient.setColorAt(0.0, color1);
radialGradient.setColorAt(0.27, color2);
radialGradient.setColorAt(0.44, Qt::white);
radialGradient.setColorAt(0.76, color3);
radialGradient.setColorAt(1.0, color4);
QBrush brush = QBrush(radialGradient);
painter->setBrush(brush);
painter->drawRect(boundingRect());
}