Итак в єтой статье я розкажу вам как сделать сглаживание своими руками.
И так немножко теории...что же такое сглаживание?
Прямиком из вики получаем:
Сгла́живание —технология, использующаяся в обработке изображений с целью делать границы кривых линий более гладкими, убирая «зубцы», возникающие на краях объектов.
|
Инными словами если мы возьмем картинку нормального размера и отскейлим ее допусти в 4 раза меньше исходного размера - то получим артефакты на подобии этого:
Со сглажеванием же картинка будет выглядет намного "мягче":
Ну думаю тут все ясно....теперь перейдем к реализации:
Разбиваем имагу на сектора
Первым делом нам нужно написать функцию котая бы делила всю имагу на сектора.... желательно чтобы функция была гибка, и вы могли вольно выставлять количество секторов на которые она должна разбиватся.
По этому я сначала создал тип который содержал бы информацию каждого сектора о :
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
Вот что у меня получилось из этого :
Хм, теперь давайте разберемся зачем же эти сектора... Сектора нужны для того, чтобы мы могли по ним сгладить имагу.Итак по этапно как мы это будем именно делать:
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
Осталось назначить нужное кол-во секторов(качество), отскейлить ,сгладить и посмотреть чтоже у нас из этого вышло
:
Если у кого не получилось сделать самому
Исходны код с ресами :
Anti.rar
У кого нету бМакса, но посмотреть охота:
AntiEXE.rar