SteveK2 Ответов: 1

Gdi+ pen производит линии переменной ширины пикселей?


Может ли кто-нибудь объяснить, как работают координаты GDI+?

Я переношу большую программу MFC/C++ gdi-drawing для использования gdi+. Самый простой способ начать работу состоял в том, чтобы создать объект Gdiplus::graphics из DC, который я уже инициализировал, а затем переместить каждый элемент чертежа поперек по очереди, стараясь не переключаться между DC & gdi++. Почти все сработало мгновенно.

Итак: мысленно я думаю в gdi. Переход на gdi+ с минимальными изменениями работает, за исключением одной вещи...

В gdi+ ширина линий не постоянна. Определение пера с определенной шириной приводит к различному количеству пикселей в зависимости от того, где на экране оно нарисовано. В GDI, независимо от того, какие единицы измерения/масштабирования были объявлены, определение пера всегда приводило к постоянной ширине пикселя. Я удалил весь код инициализации режима отображения / DC, выполненный до объявления Gdiplus::graphics, но основная проблема все еще существует.

Очевидно, я что-то упускаю.

Пример кода, удаляющий всю инициализацию DC...
OnPaint >> DoDraw(CDC* pDC, CRect rPaint)

Графика графика(pDC->m_hDC);
Gdiplus::REAL sc = 1.0;

Gdiplus::REAL nPenWidth = sc * 5;
Gdiplus::Pen p(color, nPenWidth);
для (int r = 0; r < 20; r++)
{
Gdiplus::реальный y = 0.0 + (r *40);
g->DrawLine(&p, 20.0, y, 120.0, y);
}

Это рисует колонку из 20 коротких горизонтальных линий, все с помощью того же пера. На моем мониторе 96dpi некоторые имеют ширину 3 пикселя, некоторые-4 пикселя. Почему эти линии не одинаковой ширины?

Что я уже пробовал:

Замена инициализации “sc” перед определением пера улучшает согласованность, но не полностью исправляет ситуацию (так что, возможно, это отвлекающий маневр).

// уставки в единицах измерения -
графика.SetPageUnit(Gdiplus::UnitPoint);
Gdiplus::REAL dpiX = графика.GetDpiX();
Gdiplus::недвижимость СК = 72.0 / около;
графика.SetPageScale(Южная Каролина);

Richard MacCutchan

Я только что попробовал этот код, и каждая строка выглядит точно такой же ширины, даже под лупой.

SteveK2

- Спасибо, Ричард.

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

1 Ответов

Рейтинг:
1

KarstenK

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

Когда линии находятся под некоторым углом, выход должен каким-то образом решить оптимизировать и сгладить линию. Обычно это делается через некоторые расчет из окружающих пикселей. Таким образом, фон также может иметь некоторое влияние.

Хорошая обзорная статья этого искусства объясняет статью из Кембриджский университет.


SteveK2

Карстен, это была та область, где я думал, что проблема была, и бился головой о стол в течение нескольких дней.

Непосредственная проблема (переменная ширина линии) заключалась в том, что я установил MM_ISOTROPIC mapping и размер окна log/phys для масштабирования перед переключением на gdi+. Если я удалю это (& в избегающем мерцания растровом изображении памяти DC), мои линии будут выглядеть согласованными - и некоторые элементы нечетного сглаживания исчезнут.

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