Печать/сохранение QGraphicsScene в монохромное изображение очень плохого качества

Я хотел бы распечатать/сохранить QGraphicsScene в формате Mono. Я сделал так, чтобы сцена содержала только один цветной объект (в одном из окон он на самом деле черно-белый).

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, я вижу, что рендеринг в моноизображение использует Qt::ThresholdDither.

Если бы я, по крайней мере, мог применить другой дизеринг к рендерингу за один шаг, без необходимости сначала создавать цветное изображение, а затем дизеринг для нового монохромного изображения, это было бы огромным улучшением. Память и время очень важны.

Хотя, возможно, мне действительно нужен быстрый способ просмотреть каждый пиксель и установить его в 1, если его интенсивность выше 0,5, и в 0, если ниже? Это по-прежнему будет означать отдельный шаг после создания изображения rgb32, хотя... и по какой-то причине выполнение этого "вручную" всегда медленнее, чем встроенные методы.

Update2: элемент, нарисованный в этом примере, представляет собой прямоугольник с градиентной кистью. Я также разделил цвета на 4 QGraphicsScenes: если цвет == цвет1, то цвет2,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());
}

person Thalia    schedule 23.04.2015    source источник
comment
Монохромное изображение с дизерингом тоже выглядит идеально. Какая у вас конкретно проблема? Изображение без дизеринга просто пороговое, чтобы уменьшить среднюю ошибку. Вам нужно будет опубликовать полноразмерные примеры изображений и точный код, используемый для их рендеринга; если есть ошибки Qt, это будет тестовый пример. Как есть, вы не предоставляете достаточно подробностей.   -  person Kuba hasn't forgotten Monica    schedule 23.04.2015
comment
Моим входом в рендеринг является QGraphicsScene, содержащий набор объектов одного цвета. Выход должен быть монохромным растровым изображением из-за ограничений памяти. Также было бы здорово, чтобы это было как можно быстрее. Показанный мной код, который сначала визуализирует монофоническую коллекцию объектов в гигантское изображение rgb, а затем превращает гигантское изображение rgb обратно в моно, имеет следующие проблемы: (1) добавляет гигантское изображение rgb (2) добавляет очень много времени шаг (3) качество вывода низкое (точки распространения ошибок, более светлый цвет)   -  person Thalia    schedule 23.04.2015


Ответы (1)


На данный момент мое решение:

  • для каждого элемента на сцене, если он требует преобразования в изображение, поместите его на сцену вместе со всеми элементами, которые сталкиваются и находятся над ним

  • сохранить прямоугольный клип элемента сцены в цветное изображение

  • преобразовать изображение в монохромное с помощью Qt::OrderedDither, что создает меньше артефактов

  • поместите изображение на место предмета на сцене

  • преобразовать сцену в монохромную, используя значение по умолчанию (Qt::ThresholdDither)

Вероятно, это потребует меньше памяти (в зависимости от размера элементов), но с высокой вероятностью повторного применения одного и того же процесса и сохранения в формате изображения областей, которые находятся друг над другом.

person Thalia    schedule 06.05.2015