Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > 2-D Графика средствами WinAPI (ну или MFC)


Автор: CBETA 12.4.2004, 02:14
Как провести сглаженную прямую, окружность, многоугольник?
Не знаю как это называют профи, поэтому попытаюсь объяснить что я подразумеваю под термином "сглаженная"
Например: (условный код)
MoveTo(0,0);
LineTo(10,1);
Линия будет нарисована со ступенькой вроде этого:
-----_____
Если же такую линию провести например в Фотошопе то она будет смотреться на много изящнее.
Изобразить здесь не смогу. (в общем это нужно видеть.)

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

Автор: chipset 12.4.2004, 05:27
В фотошопе используется метод антиалиасинга то есть пиксель немного расплывается, и высчитывается состояние отдельных клеток по X или + образному методе.
Подробнее об антиалиасинге читай вот http://www.mycomp.com.ua/article.php?id=3753 .
А насчёт GDI-ных функций, то ИМХО для нормального проекта GDI сильно тормознутый...
Лучше заюзать DirectX или OpenGL, в иксе скорее всего и есть такии функции но точно не могу сказать...
Удачи!

Автор: achmed 12.4.2004, 16:14
ну наверное стоит поискать готовые MFCшные классы, реализующие эту функциональность,
где-нибудь на codeproject.com, codeguru.com/

Автор: Coocky 12.4.2004, 20:13
Цитата
Как провести сглаженную прямую, окружность, многоугольник?

Это не есть задачи МФС.По крайней мере функций таких не встречал.Для этого есть библиотеки Opena и Directa.Кстати под этими библиотеками прекрасно работает видеокарта,(если поставить настройки smile.gif )Все прекрасно сглаживает biggrin.gif А вот функции тормозят прогу sad.gif

Автор: CBETA 13.4.2004, 02:07
chipset[b]
[b]Coocky

Фокус с картой не пройдет. Условия варварские smile.gif.
Проект должен работать на любой машине, начиная с 486 и Win95.
По этой же причине видимо Open и Direct отпадают.
Не поставлять же этих монстров вместе с прогой.
А на Win95 какой там был директ, и был ли вообще?

На самом деле экстра быстродействия не требуется.
Думаю вполне достаточно быстродействия GDI.
Если честно, просто не хочется изобретать велосипед.

achmed
Поискать попробую, хотя мне почему-то никогда не удается
найти именно то что нужно. (Видимо искать не умею.)

И еще вопросик по теме:
Как сделать градиентную заливку прямоугольника средствами GDI?

Приходит в голову что-то вроде бесконечного создания и удаления кистей разных оттенков.
Писать еще не пробовала, но должно выглядеть ну очень забавно. smile.gif

Автор: mr.DUDA 13.4.2004, 15:14
Цитата
И еще вопросик по теме:
Как сделать градиентную заливку прямоугольника средствами GDI?

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

На самом деле всё гораздо проще wink.gif:
Цитата
void CGradientView::OnDraw(CDC* pDC)
{
    // выбираем "крайние" цвета градиентной заливки
    COLORREF col1(RGB(255,0,0)), col2(RGB(0,0,255));

    // определяемся с размерами прямоугольника
    int W=200, H=100;

    // создаём рабочий Bitmap и получаем его пикселы как массив цветов
    CBitmap bmp; bmp.CreateCompatibleBitmap(pDC, W, H);
    COLORREF *pPixels = GetBitmapPixels(bmp, W, H);

    // проходим в цикле по пикселам, рисуем градиент "наискосок"
    for(int y=0; y<H; y++)
        for(int x=0; x<W; x++)
            pPixels[x+y*W] = Gradient(col1, col2, x+y, W+H);

    // применяем массив цветов на Bitmap, выводим Bitmap в окно
    SetBitmapPixels(bmp, pPixels);
    pDC->DrawState(CPoint(0,0), CSize(W,H), &bmp, DST_BITMAP|DSS_NORMAL);
}

Функции GetBitmapPixels и SetBitmapPixels были подробно описаны в FAQ, вот в http://forum.vingrad.ru/index.php?showtopic=17344&view=findpost&p=116315, а текст функции Gradient - предельно простой:
Цитата
COLORREF Gradient(COLORREF col1, COLORREF col2, int n, int nMax)
{
    float r1=(float)(col1&0xff), g1=(float)((col1>>8)&0xff), b1=(float)((col1>>16)&0xff);
    float r2=(float)(col2&0xff), g2=(float)((col2>>8)&0xff), b2=(float)((col2>>16)&0xff);

    float d = (float)n/(float)nMax;
    float newr = r1+(r2-r1)*d;
    float newg = g1+(g2-g1)*d;
    float newb = b1+(b2-b1)*d;

    return RGB((int)newr,(int)newg,(int)newb);
}

Полностью проект MFC, рисующий градиентный прямоугольник, можно скачать по ссылке:

Автор: CBETA 14.4.2004, 02:12
mr.DUDA
Работа с Bitmap как с массивом точек. Действительно просто, когда знаешь.
Кажется то что надо, Спасибо.
До остального дойду сама. (надеюсь)

Автор: CBETA 14.4.2004, 02:38
mr.DUDA
А файлик то 0-oй длины

Автор: mr.DUDA 14.4.2004, 09:31
Цитата
А файлик то 0-oй длины

И в самом деле. Что-то глюкнуло, наверное...
Вот рабочий линк:

Автор: mr.DUDA 14.4.2004, 09:34
Картинка получается такая:

Автор: CBETA 4.5.2004, 02:28
Извиняюсь, что поднимаю старую тему,
но мне кажется что тут (вернее в FAQе) есть небольшая ошибка.
Функции:
COLORREF *GetBitmapPixels(CBitmap &Bmp, int &W, int &H);
void SetBitmapPixels(CBitmap &Bmp, COLORREF *pPixels);

Чтоб они работали с (COLORREF*) нужно переставлять байты у массива.
причем 2 раза, при Get.. и при Set.. (доп. время)

Или хотя-бы бы переписать вот так:
RGBQUAD *GetBitmapPixels(CBitmap &Bmp, int &W, int &H);
void SetBitmapPixels(CBitmap &Bmp, RGBQUAD *pPixels);

Если я не ошибаюсь, RGBQUAD не совсем COLORREF

из МСДН:
Цитата
RGBQUAD
typedef struct tagRGBQUAD {
  BYTE    rgbBlue;
  BYTE    rgbGreen;
  BYTE    rgbRed;
  BYTE    rgbReserved;
} RGBQUAD

Если переписать в том виде как храниться в памяти будет:
BB GG RR 00

Еще из МСДН:
Цитата
The COLORREF value is used to specify an RGB color.
typedef DWORD COLORREF;
Remarks
When specifying an explicit RGB color, the COLORREF value has the following
hexadecimal form: 0x00bbggrr

Если и это переписать в том же виде:
RR GG BB 00

Только ради бога, не ругайте слишком сильно если я не права.
Путаница с цветами. Запуталась совсем.

Автор: mr.DUDA 4.5.2004, 09:23
Thanks !!!

Тема в FAQ отредактирована. Ситуация с перестановкой цветов была решена вот так:
Цитата
struct DIBCOLOR
{
   
BYTE b;
   
BYTE g;
   
BYTE r;
   
BYTE reserved;
   
DIBCOLOR(BYTE ar,BYTE ag,BYTE ab):
   
r(ar), g(ag), b(ab), reserved(0) {}
   
operator DWORD() {return *reinterpret_cast<DWORD*>(this);}
};

Тогда вместо RGB и COLORREF-макросов можно использовать DIBCOLOR. Можно сравнивать между собой два DIBCOLOR-а.

Автор: CBETA 5.5.2004, 02:52
mr.DUDA
Замучаю до конца smile.gif
Конструктор:
DIBCOLOR(BYTE ar,BYTE ab,BYTE ag):
...
лучше переписать так
DIBCOLOR(BYTE ar,BYTE ag,BYTE ab):
...

Порядок следования R,G,B имхо, болле привычен.

Автор: mr.DUDA 5.5.2004, 13:16
Ну, СВЕТА, погоди ! adv/protest.gif

Исправил.

Автор: AndyY 8.5.2004, 12:25
Кстати - есть либа GDI+, в ней есть обработка антиалиасинг.
по умолчанию входит в XP, редистрибутивна (работает под 98 и 2000).
тяжелая, правда.

Автор: Alex B@D 8.5.2004, 17:59
Простите я пОООлный ламер (пока еще )
adv/168.gif
И хочу узнать почему делфовский канвас(Canvas)в С++ BUILDER не пашет????

Автор: shara 29.6.2004, 03:20
если комуто интересно - то я могу прислать код проги которая гладкой кривой соеденяет точки по методу B-Spline. Просто мне прогу набирать что-то совсем не хочется smile.gif .

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)