forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   FAQ и уроки (http://forum.boolean.name/forumdisplay.php?f=110)
-   -   Разбираемся в : Antialiasing (http://forum.boolean.name/showthread.php?t=13426)

Dzirt 29.09.2010 14:29

Разбираемся в : Antialiasing
 
Вложений: 6
Итак в єтой статье я розкажу вам как сделать сглаживание своими руками.
И так немножко теории...что же такое сглаживание?
Прямиком из вики получаем:
Цитата:

Сгла́живание —технология, использующаяся в обработке изображений с целью делать границы кривых линий более гладкими, убирая «зубцы», возникающие на краях объектов.
Инными словами если мы возьмем картинку нормального размера и отскейлим ее допусти в 4 раза меньше исходного размера - то получим артефакты на подобии этого:
Вложение 11400

Со сглажеванием же картинка будет выглядет намного "мягче":
Вложение 11401

Ну думаю тут все ясно....теперь перейдем к реализации:

Разбиваем имагу на сектора
Первым делом нам нужно написать функцию котая бы делила всю имагу на сектора.... желательно чтобы функция была гибка, и вы могли вольно выставлять количество секторов на которые она должна разбиватся.
По этому я сначала создал тип который содержал бы информацию каждого сектора о :
1.Начальной координате Х
2.Начальной координате У
3.Высоте сектора
4.Шириге сектора
5.Его порядкового ид(это не так уж и нужно, но посколько данная функция может еще использоватся и в качестве отладки, то лучше таки создать это поле)
Код:

Type sector
    Field x:Float
    Field x2:Float
    Field y:Float
    Field y2:Float
    Field id
EndType

Далее пишем собственно саму функцию.Она должна быть гибкой и работаь с разными имагами поэтому в заголовке пишем:
Код:

Function sectors(image,sectors,ImageX,ImageY)
Параметры использованые в функции:
1.image - собственно картинка которую мы будет сглаживать
2.sectors - это количество секторов на которое мы будем ее делить.(какое должно быть их количество и зачем они вообще нужну опишу далее)
3.ImageX- начальная координата Х имаги, это нам понадобится при работе с пиксмапами.
4.ImageY - начальная координата У имаги,это нам понадобится при работе с пиксмапами.

Как разделить картинку на равное количество секторов - конечно все мы знаем: Делим ширину и высоту картинки на кол-во секторов и получаем ширину и высоту каждого сектора.

Код:

    sectorsW:Float=ImageWidth(image)/sectors
    sectorsH:Float=ImageHeight(image)/sectors

Итак вообщем вот конечная функция(я люблю пользоватся временными переменными в функции...вам желаю избавится от этой привычки или просто не развивать ее, так как собирается иногда много мусора в функции) :
Код:

'Divine image to sectors
Function sectors(image,sectors,ImageX,ImageY)
    sectorsW:Float=ImageWidth(image)/sectors
    sectorsH:Float=ImageHeight(image)/sectors
    tempImageX:Float=ImageX
    tempImageY:Float=ImageY

    For c=1 To sectors
        For i=1 To sectors
            sid=sid+1
            NewSector: sector= New sector
            NewSector.x=ImageX
            NewSector.y=ImageY
            NewSector.x2=sectorsW
            NewSector.y2=sectorsH
            NewSector.id=sid
            sector_list.AddLast NewSector   

            ImageX=ImageX+sectorsW
        Next
        ImageX=tempImageX
        ImageY=ImageY+sectorsH
    Next

End Function

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

    For NewSector : sector = EachIn sector_list
            SetAlpha 0.1
            SetColor 0,0,0
            DrawRect NewSector.x,NewSector.y,NewSector.x2,NewSector.y2
            SetColor 0,255,0
            DrawRect NewSector.x+1,NewSector.y+1.0,NewSector.x2-1.0,NewSector.y2-1.0
            SetColor 255,255,255
            SetAlpha 1
            DrawText NewSector.id,NewSector.x+NewSector.x2/2.5,NewSector.y+NewSector.y2/2.5
      Next

Вот что у меня получилось из этого :
Вложение 11396

Хм, теперь давайте разберемся зачем же эти сектора... Сектора нужны для того, чтобы мы могли по ним сгладить имагу.Итак по этапно как мы это будем именно делать:
1.Имага розбита на сектора
2.С помощю перебора каждого сектора мы вычислим какой цвет для него средне-статистичен(инными словами посмотрим каждый пиксель который содержит сектор и возьмем среднее значение цвета.)
3.Закрасим весь секор средним цветом из полученого в этапе 2 значения.

Не сложно догадатся что чем бльше секторов мы сделаем - те качественее будет сглаживание, но и втоже время увеличит время обработки.

Функция сглаживания
Итак приступим к самой функции сглаживания:
1.Для начала нужно знать что чтобы рабоать с имагой в Бмаксе нам нужно сначала поставить ей флаг DYNAMICIMAGE. Делаем это при загрузке имаги :
Код:

mainImage=LoadImage("sammple.png",DYNAMICIMAGE )
+ при работе с пиксмапой ее прийдется заблокировать :
pixmap=LockImage(image)
ну а потом естественно разблокировать
UnlockImage(image)


Также следует знать что при работе с пикселями пиксмапы, Бмакс пользуется интом ARGB.Чтобы его розложить на стандартный А,R,G,B нужно попарится немножко... но вот вам фугкции намного упрощающие задачу:

1.Функйия переформатирования из стандартный А,R,G,B в инт ARGB:
Код:

Function SetARGB(a=255,r=255,g=255,b=255)
    Return (((a) Shl 24) + ((r) Shl 16) + ((g) Shl 8) + (b))
End Function

2.Функция вытаскивания значения R из инта:
Код:

Function IntR(rgbint)
    Return ((rgbint Shr 16) & $ff)
End Function

3.Функция вытаскивания значения G из инта:
Код:

Function IntG(rgbint)
    Return ((rgbint Shr 8) &  $ff)
End Function

4.Функция вытаскивания значения B из инта:
Код:

Function IntB(rgbint)
    Return (rgbint & $ff)
End Function

5.Функция вытаскивания значения А из инта:
Код:

Function IntA(rgbint)
    Return ((rgbint Shr 24) & $ff)
End Function


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

TempA=IntA(pixel)
TempR=IntR(pixel)
TempG=IntG(pixel)
TempB=IntB(pixel)
                                                                                       
GlobalSectorA=GlobalSectorA+TempA
GlobalSectorR=GlobalSectorR+TempR
GlobalSectorG=GlobalSectorG+TempG
GlobalSectorB=GlobalSectorB+TempB

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

Функция сглаживания:
Код:

'main antialiase function
Function antialiase(image)

    pixmap=LockImage(image)
        For NewSector : sector = EachIn sector_list
            temp_valX=NewSector.x-imageX
            temp_valX2=(NewSector.x2+NewSector.x)-imageX
            temp_valY=NewSector.y-imageY
            temp_valY2=(NewSector.y2+NewSector.y)-imageY
            GlobalSectorA=0
            GlobalSectorR=0
            GlobalSectorG=0
            GlobalSectorB=0
            count=0
   
                For h=temp_valY  To temp_valY2-1
                    For w=temp_valX To temp_valX2-1
                        count=count+1
                        pixel=ReadPixel (pixmap,w,h)
                        TempA=IntA(pixel)
                        TempR=IntR(pixel)
                        TempG=IntG(pixel)
                        TempB=IntB(pixel)
                                                                                       
                        GlobalSectorA=GlobalSectorA+TempA
                        GlobalSectorR=GlobalSectorR+TempR
                        GlobalSectorG=GlobalSectorG+TempG
                        GlobalSectorB=GlobalSectorB+TempB

                    Next
                Next
               
                GlobalSectorA=GlobalSectorA/count
                GlobalSectorR=GlobalSectorR/count
                GlobalSectorG=GlobalSectorG/count
                GlobalSectorB=GlobalSectorB/count

                For h=temp_valY  To temp_valY2-1
                    For w=temp_valX To temp_valX2-1
                        pixel=WritePixel (pixmap,w,h,SetARGB(GlobalSectorA,GlobalSectorR,GlobalSectorG,GlobalSectorB))
                    Next
                Next
   
        Next           
   
    UnlockImage(image)
    Return image
EndFunction

Осталось назначить нужное кол-во секторов(качество), отскейлить ,сгладить и посмотреть чтоже у нас из этого вышло :) :

Вложение 11397


Если у кого не получилось сделать самому
Исходны код с ресами :Вложение 11398

У кого нету бМакса, но посмотреть охота:
Вложение 11399

ABTOMAT 29.09.2010 15:36

Ответ: Разбираемся в : Antialiasing
 
Это не антиалязинг, а блюр. Но всё равно годно, спасибо.


Часовой пояс GMT +4, время: 21:12.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot