Jest to blog poświęcony nowoczelnym technologiom ułatwiającym tworzenie aplikacji internetowych. Znajdziesz tutaj porady na temat CSS3, JavaScript, designu, web-usability, standardów W3C.
Cześć! Nazywam się Michał Środek. Z zawodu programista php, z zamiłowania gitarzysta oraz fanatyk GNU/Linuksa(openSUSE® w laptopie). W branży aplikacji internetowych od 9 lat. Prywatnie bez dzieci i kota.
Pracuję wciąż nad własnym elastycznym i wydajnym frameworkiem MVC, kilkoma portalami internetowymi oraz mniejszymi bibliotekami php. Czekam na wasze opinie, zgłoszenia błędów oraz pomysły na dalszy rozwój.
Ta część strony jest w trakcie budowy a moje prace tymczasowo niedostępne.
W przypadku pytań, ofert pracy oraz ciekawych pomysłów proszę się ze mną kontaktować. Możesz mnie znaleźć i wysłać PW na php.pl(SHiP), jamendo.com(michalsrodek), goldenLine.pl, facebook.com lub nk.pl
Pracuję aktualnie nad oskryptowaniem, które zostanie użyte na stronie mojego przyjaciela(http://szescian.pl/). Sęk w tym, że jego bujna wyobraźnia wygenerowała coś, z czym mogę mieć niemałe problemy. Mówiąc krótko: dużo matematyki oraz sporo generowania wielokątów. Postanowiłem, że użyję do tego celu technologii canvas. Mając chwilę czasu chciałbym się z wami podzielić kilkoma fajnymi technikami. O rysowaniu wielokątów napiszę innym razem. Dzisiaj chciałbym pokazać wam coś co dla wielu prawdopodobnie wydawałoby się niemożliwe
. Spróbujemy przekonwertować, piksel po pikselu, obrazy za pomocą JavaScript.
Jako obraz poglądowy wybrałem jedno z moich zdjęć:

Spróbujmy najpierw stworzyć obiekt canvas, nadać mu identyfikator oraz po prostu wczytać do niego obrazek.
<canvas id="myCanvas" width="600" height="150">Brak obsługi Canvas</canvas>
// wybranie elementu <canvas> var myCanvas = document.getElementById('myCanvas'); // sprawdzenie czy można pobrać kontekst if (myCanvas.getContext) { // pobranie "kontekstu 2d" var ctx = myCanvas.getContext('2d'); if (ctx) { // stworzenie nowego obrazka var img = new Image(); // okreslenie adresu img.src = '/examples/canvas1/mini.jpg'; // stworzenie zdarzenie wywołanego po wczytaniu obrazka img.addEventListener('load', function () { // rysuj obrazek rozpoczynajac od wspolrzednych 0,0 pola canvas ctx.drawImage(this, 0,0, 150, 150);
Kolejnym krokiem jest wczytanie informacji o pliku. Chcę stworzyć 3 modyfikacje mojego zdjęcia więc robię to trzykrotnie.
// Get the pixels. var imgdata = ctx.getImageData(0, 0, 150, 150); var imgdata2 = ctx.getImageData(0, 0, 150, 150); var imgdata3 = ctx.getImageData(0, 0, 150, 150);
Spróbujmy wykonać pierwsze przekształcenie polegające na konwersji zdjęcia do palety szarości.
var pix = imgd.data; for (var i = 0, n = pix.length; i < n; i += 4) { pix[i] = 0.2989*pix[i] + 0.5870*pix[i+1] + 0.1140*pix[i+2]; // czerwony pix[i+1] = 0.2989*pix[i] + 0.5870*pix[i+1] + 0.1140*pix[i+2]; // zielony pix[i+2] = 0.2989*pix[i] + 0.5870*pix[i+1] + 0.1140*pix[i+2]; // niebieski } ctx.putImageData(imgdata, 150, 0);
Krótkie wytłumaczenie:
Najpierw została pobrana tablica pikseli. Sposób zapisu danych na ich temat jest troszkę nietypowy. Każdy piksel jest mieszaniną trzech(czerwony, zielony, niebieski) kolorów oraz współczynnika przezroczystości. Dlatego, nasza tablica posiada 90 tys. elementów(150x150x4). Skacząc w pętli co cztery elementy, za każdym razem otrzymujemy nowy piksel do przebadania. Każdy z nich jest przekształcany na jeden z odcieni szarości. Na końcu obraz jest umieszczany w miejscu o współrzędnych 150,0(pierwszych 150 pikseli zajmuje nieprzekształcone zdjęcie, które umieściliśmy już wcześniej.
Spróbujmy odwrócić kolory:
var pix = imgdata2.data; for (var i = 0, n = pix.length; i < n; i += 4) { pix[i] = 255 - pix[i]; // czerwony pix[i+1] = 255 - pix[i+1]; // zeilony pix[i+2] = 255 - pix[i+2]; // niebieski } ctx.putImageData(imgdata2, 300, 0);
Ostatnim przekształceniem będzie zabawa z kolorami
. Wydzieliłem również pas pikseli, który będzie przekształcany w inny sposób. W ten sposób można tworzyć efekty punktowe(np. podświetlić na biało oczy).
var pix = imgdata3.data; for (var i = 0, n = pix.length; i < n; i += 4) { if(i<15000 || i> 75000){ pix[i ] = 25+pix[i]/2+pix[i+1]/5; // czerwony pix[i+1] = 25+pix[i+1]/2+pix[i+2]/5 ; // zielony pix[i+2] = 25+pix[i+2]/2+pix[i]/2; // niebieski } else { pix[i ] = pix[i]; // czerwony pix[i+1] = pix[i+1]/2+50 ; //zielony pix[i+2] = pix[i+2]/2+40; // niebieski } } ctx.putImageData(imgdata3, 450, 0);
Oczywiście musimy jeszcze uzupełnić parametry funkcji oraz zamknąć wszystkie nawiasy.
}, false); } }
Pamiętajmy jednak, że element canvas jest niedostepny w starszych przeglądarkach Internet Explorer. Jeśli się nie mylę dopiero 9 wersja zacznie go obsługiwać poprawnie.
Cały przykład dostępny w postaci pliku js: canvas.js
Efekt działania:
Dla IE we wcześniejszych wersjach napisano już skrypty, które emulują obiekt Canvas. Takie coś walnąć w komentarz warunkowy i będzie dobrze
Komentarz by kilas — 18 kwietnia 2010, 0:00
Teraz to mnie zagiąłeś
Nie sądziłem, że coś takiego jest do wykonania… Z pewnością wykorzystam to w przyszłych projektach. Przyda się do miniaturek w galerii. Dzięki i pozdrawiam
Komentarz by Oskar Wójcicki — 24 kwietnia 2010, 11:24
Nie wiem czy wykorzystanie tego w galerii to świetny pomysł — wydajność przeglądarek wciąż pozostawia wiele do życzenia. Ja prawdopodobnie użyję tego w swoim blogrollu, ale jeszcze nie teraz ;].
Komentarz by Michał Środek — 24 kwietnia 2010, 12:37
Hm… możesz powiedzieć dlaczego masz tak dziwny wzór do tworzenia gray scale?
[code]
pix[i] = 0.2989*pix[i] + 0.5870*pix[i+1] + 0.1140*pix[i+2];
[/code]
ja znam, średnią arytmetyczną wszystkich składowych tj:
[code]
pix[i] = ( pix[i] + pix[i+1] + pix[i+2] ) / 3;
[/code]
poza tym liczysz to samo 3 razy. Przydałaby się zmienna
Komentarz by luq — 5 czerwca 2010, 10:31
a) Rzeczywiście liczę trzy razy to samo. Kwestia podstawienia do zmiennych
pix[i] = pix[i+1] = pix[i+2] = 0.2989*pix[i] + 0.5870*pix[i+1] + 0.1140*pix[i+2];
b) Wzór ten wskazał mi brat zajmujący się programowaniem grafiki. Powiedział mi, że wynika to z większego skupiania uwagi na zielonych barwach przez ludzkie oko(nie pamiętam dokładnie co powiedział ale chodziło o ludzką percepcję barw). Wierzę mu na słowo
. Jak znajdę jakieś informacje w sieci to wkleję link.
EDIT:
Znalazłem ciekawy wpis na stackoverflow http://stackoverflow.com/questions/687261/converting-rgb-to-grayscale-intensity
To co pokazałem to Y-Greyscale (YIQ/NTSC): Red: 0.299 Green: 0.587 Blue: 0.114 ale są również inne rodzaje szarości np.
– BT709 Greyscale: Red: 0.2125 Green: 0.7154 Blue: 0.0721
– RMY Greyscale: Red: 0.5 Green: 0.419 Blue: 0.081
Komentarz by Michał Środek — 5 czerwca 2010, 12:18
No bo właśnie już kiedyś spotkałem się z podobnym wzorem i nie wiedziałem dlaczego w taki sposób to ktoś liczy. Okej poczytam, dzięki za info
Dla zainteresowanych zrobiłem mały test, ja wygląda obrazek po przekształceniu zgodnie każdym algorytmem:
orginał
R, G, B = (R+G+B) / 3
Y-Greyscale
RMY-Greyscale
BT709-Greyscale
Tak, btw. u Ciebie wpisuje się BBCode czy znaczniki html‚a? <a> czy [link]?
Komentarz by luq — 6 czerwca 2010, 17:53