luq techblog

o tworzeniu słów kilka…

Filtrów ciąg dalszy… 19 listopada 2009

Filed under: PHP,Programowanie — Łukasz @ 19:26
Tags: , ,

Witam od niepamiętnych czasów. Brak pomysłów na wpisy jak i czasu spowodował tak długą przerwę, aktualnie jestem chory także mogłem napisać ten wpis.

 

Już dawno, pojawił się wpis o mojej własnej klasie do manipulacji obrazkami z wykorzystaniem GD. Jednak po tych kilku miesiącach, gdzie coraz częściej zdarza mi się pisać obiektowo, (właściwie wyłącznie obiektowo) stwierdziłem, że klasa jest bez sensu. Właściwie do początku miałem świadomość tego, że jest to kontener na funkcję (praktycznie wszystkie metody były statyczne). Było tak dlatego aby pozostawić sobie możliwość tworzenia dwóch przekształceń obrazka np. do połowy ta samo – mamy oryginalny obrazek z którego chcemy stworzyć jego wersję obróconą wertykalnie + skala szarości oraz drugą wersję obróconą wertykalnie + powiedzmy negatyw. Ale przecież jest można klonować obiekty wykorzystując clone.

 

Tak więc siadłem kiedyś do modernizacji klasy (prace dokończyłem dzisiaj), i chciałbym zaprezentować jej możliwości, a przy okazji opisać jak operuje się na pixelach aby otrzymać takie proste filtry.

 

Przyda się kilka wyjaśnień co do używanych prze zemnie terminów, które są w zasadzie trywialne, ale dla mniej siedzących w temacie, tłumacze. Jeden kolor (jeden pixel wyświetlany na ekranie) składa się z 3 barw składowych (3 subpixeli) w których skład wchodzą Red, Green oraz Blue. Dodatkowo używane jest także czwarte „pole” tzw. kanał alpha, który mówi nam o przezroczystości wynikowej barwy. Każda składowa mówiąca o kolorze może przyjmować wartość od 0 do 255, natomiast kanał alpha jest ograniczony od 0 do 127. Kolory otrzymujemy mieszając składowe RGB, a przez to że mamy dostępnych 256^3 kombinacji poszczególnych składowych możemy stworzyć 16.581.375 różnych barw. Co do kanału alpha. Jeżeli jest on równy 127 to pixel jest niewidoczny (właściwie maksymalnie przezroczysty), natomiast jeśli jest równy 0 – pixel jest całkowicie widoczny. Jeszcze chyba ostatnia informacja. W komputerach grafika jest przedstawiana w układnie współrzędnych innym niż kartezjański. Nie mamy wartości ani argumentów ujemnych, więc wygląda to tak – lewy górny róg ekranu (obrazka or sth.) to punkt (0, 0), iksy rosną ku prawej, natomiast igreki ku dołowi.

 

A oto zdjęcie na którym będziemy pracować:

Zaczynamy.

  • Skala szarości
  • Gray scale otrzymujemy poprzez przypisanie każdej składkowej koloru średniej arytmetycznej wszystkich 3.
    Przykład: R = 255, G = 197, B = 97, średnia arytmetyczna to (255 + 197 + 97)/3 = 183, a więc ten pixel w skali szarości będzie miał R = 183, G = 183 oraz B = 183.

  • Negatyw
  • Negatyw sprawia, że barwa zamieniana jest na przeciwną. Dla 0 daje 255, a dla 255 otrzymamy 0.
    Przykład: R = 255, G = 197, B = 97, R = 255 – 255 = 0, G = 255 – 197 = 58, B = 255 – 97 = 158

  • Obrót horyzontalny
  • Obrót horyzontalny to bardzo prosty filtr. Najlepiej wytłumaczyć go chyba w ten sposób. Wyobrażamy sobie że malujemy pionową krechę przechodzącą dokładnie przez środek zdjęcia, i teraz cyrklem każdy pixel z prawej strony kreski przenosimy na lewą a z lewej na prawą pozostawiając dokładnie taką samą odległość tego pixela od kreski.
    Programistycznie rzecz biorąc, problem rozwiązuje się tak: leci się po wszystkich pixelach najpierw wierszę potem zmiana kolumny i to samo (jak zresztą w wielu filtrach), i przekłada się pixele na drugą stronę. Nowe położenie X = (szerokość obrazka – 1) – aktualne X.
    Przykład: obrazek 100×50. Bierzemy pierwszy pixel (x=0, y=0), i wstawiamy go w miejsce (x=(100-1)-0, y=0) co daje (x=99, y=0), i tak dalej dla kolejnych pixeli. Dwie uwagi. Dlaczego jest „szerokość obrazka – 1”, a no dlatego że mając obrazek o szerokości 100 pixeli pierwsza kolumna to x=0 natomiast ostatnia to x=99, pełen zakres daje 100. Po drugie należy zastosować jakiś bufor, aby nie zrobić powielenia horyzontalnego. Jeśli jedziemy kolejno pixelami od lewej do prawej (od x=0 do x=szerokosc obrazka-1), to po przejechaniu połowy mamy całą lewą stronę skopiowaną na stronę prawą, więc jadąc dalej nic już się nie zmieni. Można to rozwiązać na dwa sposoby. Użyć nowego obrazka do rysowania albo lecieć ostatni z lewej, ostatni z prawej, przedostatni z lewej, przedostatni z prawej… stosując tempa na barwę.

  • Powielenie horyzontalne
  • Można to wykonać tak jak podano wyżej, lecąc jedynie do środka obrazka (lub całą szerokość, nie stosując żadnego bufora, to bez znaczenia, ale oczywiście mniej optymalne), lub można by to wykonać w taki sposób: kopiujemy połowę obrazka (prawą lub lewą) obracamy ją horyzontalnie i wklejamy w miejsce przeciwnej niż kopiowana połówka.

  • Obrót wertykalny i powielenie wertykalne
  • Działa dokładnie tak samo jak operacje horyzontalne z tą różnicą, że tutaj nasza wyobrażona kreska jest pozioma, oczywiście również na środku. Tutaj zmieniamy y a nie x. Nowe położenie Y = (wysokość obrazka – 1) – aktualne Y

  • Przezroczystość
  • Filtr polega na dodaniu do każdego pixela tej samej wartości kanału alpha. Trzeba pamiętać, że przezroczystości nie obsługują wszystkie formaty graficzne, działają np. w PNG.

  • Progowanie
  • Tworzy tzw. obraz binarny, który składa się jedynie z dwóch barw (nazywanych dalej kolorem jasnym i ciemnym), najczęściej sobie przeciwnych (czerń i biel). Filtr przekształca pixele poniżej progu na kolor ciemny, natomiast te powyżej na kolor jasny, wszystko na podstawie średnie arytmetyczniej z RGB.
    Przykład: Próg ustawiony na 50, jasny kolor to R = 255, G = 255, B = 255, ciemny to R = 0, G = 0, B = 0, mamy pixel R = 37, G = 70, B = 0, średnia z wartości to (37 + 70 + 0)/ 3 = 35,(6) co jest < 50, a więc ten kolor zostanie zastąpiony barwą ciemną R = 0, G = 0, B = 0

  • Odszumianie
  • Pozbawianie obrazów binarnych szumu. Za szum uważany jest pixel barwy ciemnej, który ma miej sąsiednich pixeli o takiej samej barwie niż wartość uważana za szum (podaną w filtrze).
    Przykład: wartość szumu ustawiona na 3, mamy pixel barwy ciemnej a wokół niego tylko jednego sąsiada, który ma ciemną barwę, 1 < 3 więc pixel zamieniany jest na barwę jasną.

  • Liniowa przezroczystość
  • Czyli przezroczystość która zmienia się wraz z przejściem dalej osią Y. Nie ma co więcej tłumaczyć.

Dodatkowo do klasy podstawowej istnieje klasa która dziedziczy od niej ExtraFilter, która zawiera podobnie jak w poprzedniej wersji narazie tylko jedną metodą to tworzenia coverów, czyli odbicia okładek płyt. Wygląda to tak, dajemy klasie takie zdjęcie:

odpalamy metodą i otrzymujemy:

Na koniec oczywiście paczka z klasami

Reklamy
 

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s