Я хотел бы распечатать / сохранить QGraphicsScene
в моно формате. Я заставил сцену содержать только один цветной объект (в одном из окон он на самом деле черно-белый).
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();
}
Качество черно-белого изображения очень плохое!
Я ожидал, что красные пиксели станут черными, но только некоторые из них сделали. Для 4-й панели я ожидал, что все черные пиксели будут размещены как черные на монофоническом выходе, но опять же, только некоторые из них сделали.
Есть ли способ сделать черно-белое изображение с черными пикселями, где объект имеет цвет, и белым в другом месте?
Я могу легко изменить код, который генерирует цветовые участки, чтобы выводить черный вместо исходного цвета, но это, похоже, не решает проблему (4-я панель имеет черный цвет, но моно изображение не содержит всех пикселей ).
Мне нужно моно из-за стоимости памяти …
Как сделать так, чтобы сцены правильно выводились в QImage?
Update1: Я даже пытался сменить цветное изображение — результат был пугающим (слишком светлый в областях, которые должны быть темнее, странные артефакты, плюс я добавляю дополнительный шаг, который занимает много времени и, что хуже всего, добавляя очень большое изображение RGB. .. чего именно я пытаюсь избежать, мне нужно монохромное изображение из-за очень ограниченных ресурсов)
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");
Играя со встроенными методами qt dither, я вижу, что рендеринг в моно изображение использует Qt::ThresholdDither
,
Если бы по крайней мере я мог применить другой рендеринг к рендерингу за один шаг, без необходимости сначала создавать цветное изображение, а затем — новый монохромный, это было бы огромным улучшением. Память и время очень важны.
Хотя, возможно, мне действительно нужен быстрый способ пройти каждый пиксель и установить его на 1, если его интенсивность выше .5, и на 0, если ниже? Это все равно будет означать отдельный шаг после создания образа rgb32 … и по какой-то причине делать это «вручную» всегда медленнее, чем встроенные методы.
Update2: элемент, нарисованный в этом примере, представляет собой прямоугольник с градиентной кистью. Я также разделил цвета на 4 QGraphicsScenes: если color == color1, то color2,3,4 = Qt :: white и так далее.
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());
}
На данный момент мое решение:
для каждого элемента на сцене, если требуется преобразовать его в изображение, поместите его на сцену вместе со всеми объектами, которые сталкиваются и находятся над ним
сохранить прямоугольник клипа объекта в цветное изображение
преобразовать изображение в монохромный, используя Qt::OrderedDither
, что создает меньше артефактов
разместить изображение на месте предмета на сцене
конвертировать сцену без монохромного использования по умолчанию (Qt::ThresholdDither
)
Это может потребовать меньше памяти (в зависимости от размера элементов), но с высокой вероятностью многократно применять один и тот же процесс и сохранять в формате изображения области, расположенные друг над другом.