środa, 9 kwietnia 2014

Przelatywanie po tablicy - pętla for, pętla foreach | PHP

Piękno programowania znajduje się w tablicach. Odpowiednie szufladki tablicowe pomogą nam w dyskretny sposób przechować nasze dane, a liczne funkcje tablicowe wykonanie na danych chcianej operacji. Stwórzmy sobie przykładową tablicę, od razu dając do "szufladek" wartości i wypiszmy ją za pomocą konstrukcji rodem z C++, czyli zwykłym forem

Pętla for

$tablica = array(13,34,12,19,46,3);

for($i=0;$i<count($tablica);$i++){
    echo $tablica[$i].'<br/>';
}
W tablicy mamy nasze numery do dużego lotka, aby przelecieć po wszystkich sześciu liczbach użyliśmy pętli for. Co się w niej dzieje? Mówimy jej tak: najpierw zacznij od 0 (nasze $i), rób dopóki nasze $i będzie mniejsze od ilości elementów tablicy, a po każdym wykonanym przebiegu dodaj do $i jedyneczke (magiczne $i++). Jeśli nasze $i będzie już równe ilości tablicy to pętla się nie wykona (sprawa indeksu zerowego w innym poście). W środku echujemy nasze elementy z odpowiednimi indeksami i widzimy na ekranie nasze szczęśliwe liczby.

Pętla foreach

foreach($tablica as $key=>$value){
    echo 'indeks: '.$key.' wartość: '.$value.'<br/>';
}

echo 'Witaj w gronie milionerów;)';
Aby za każdym razem nie forować się możemy użyć przyjaźniejszej konstrukcji mianowicie pętli foreach. Wytłumaczenia wymagają tylko dwie zmienne: $key - oznacza indeks tablicy (oczywiście liczony od zera jak nas uczył Grębosz), $value - dane znajdujące się pod danym indeksem (nasza liczba z lotka). Na samym końcu widzimy informację o wyniku losowania w telewizji za pomocą funkcji echo .

poniedziałek, 7 kwietnia 2014

Przyłączmy się do <head> czyli załączanie zewnętrznych plików do strony www | Programowanie

W kodowaniu strony www nadchodzi wreszcie czas by ustrukturyzować nasze wypociny w bardziej przystępny sposób. Podstawą będzie dołączenie zewnętrznych plików z kodem CSS (kaskadowe arkusze styli) i javascript. Czynność tą należy uczynić w sekcji  <head> .... </head> znajdującą się tuż po znaczniku <html>.

Załączenie plików CSS

Nasz kod css znajduje się w dwóch plikach z rozszerzeniem css, przykładowo style1.css oraz style2.css. W strukturze katalogu naszej www (najczęściej public_html) tworzymy sobie folder o wdzięcznej nazwie css i w nim umieszczamy kaskadowe arkusze styli. Porządek w folderze już mamy, ale nasza strona wciąż nie ma wytycznych co gdzie i jak ma wyglądać. Pomóżmy jej wstawiając poniższe linijki w sekcji head:

<link href="css/style1.css" rel="stylesheet" type="text/css" media="all" />
<link href="css/style2.css" rel="stylesheet" type="text/css" media="all" /> 
Strona odżyła paletą barw i przyzwoitym ułożeniem poszczególnych elementów, a logo na środku już nie straszy. Pozostała nam kwestia oskryptowania naszej stronki, a z racji, że wcześniej umieszczamy kod np w folderze "js" a plik nazywa się myscript1.js w headzie pojawi się dodatkowa linijka:
<script type="text/javascript" src="js/myscript1.js"></script>

Wytłumaczenie (brak)

Mam taką zasadę, że pewnych rzeczy nie trzeba tłumaczyć, kod wydaje się być zrozumiały a tajemnicze "text/javascript" w dołączonej linijce wyjaśni się z pewnością wraz ze wzrostem umiejętności samoczynnie.

sobota, 5 kwietnia 2014

Animacja w PHP | klasa gifcreator | animacje gif

Jak zrobić animację w PHP? Chcemy warunkować nasze animację, generować ją dynamicznie, mieć wpływ na to co na obrazku ma się pojawić, czasem możemy mieć ochotę na jakąś funkcję z czasem i tak można to zrobić, z pomocą przychodzi nam PHP a dokładnie klasa gifcreator. Aby móc zacząć swoją zabawę animacyjną musimy sobie załączyć klasę z odpowiednimi funkcjami, dzięki którym tworzenie naszego gifa będzie odbywało się na "wyższym poziomie". Klasę można umieścić w osobnym pliku (i to jest wskazane przy obiektowym programowaniu), albo na potrzeby małego skryptu bezpośrednio w naszych wypocinach. Klasa wygląda tak i grzebanie w niej dla podstawowych zamiarów może wyjść nam na złe. Przyklejmy więc poniższy kod.

Klasa gifcreator: 

class gifcreator
{

    /**
     * Version
     *
     * @var string
     */
    const VERSION     = 'GifCreator v0.3';

    /**
     * Gif header
     *
     * @var string
     */
    const GIF_HEADER  = 'GIF89a';

    /**
     * Output image width
     *
     * @var int
     */
    private $_width;

    /**
     * Output image height
     *
     * @var int
     */
    private $_height;

    /**
     * Number of loops
     *
     * @var int
     */
    private $_loops    = 0;

    /**
     * Disposal method
     *
     * @var int
     */
    private $_disposal = 2;

    /**
     * Colour for transparency
     *
     * @var int
     */
    private $_colour   = -1;

    /**
     * Image frames
     *
     * @var array
     */
    private $_frames = array();

    /**
     * Global params
     *
     * @var array
     */
    private $_global = array();

    /**
     * Constructor - Setup global settings
     *
     * @param int $loops            Number of times the animation is repeated (or 0 for infinite)
     * @param int $disposal            The global frame disposal method (A value from 0 to 3)
     * @param int $transparency        The colour to use for transparency (array containing RGB values or -1 to ignore)
     * @param int $width            Width of the output image (requires GD, leave null to disable)
     * @param int $height            Height of the output image (requires GD, leave null to disable)
     */
    public function __construct($loops = 0, $disposal = 2, $transparency = array(-1, -1, -1), $width = null, $height = null)
    {
        $this->_loops     = $loops;
        $this->_disposal  = $disposal >= 0 && $disposal <= 3 ? $disposal : 2;
        $this->_colour    = $transparency[0] > -1 || $transparency[1] > -1 || $transparency[2] > -1 ?
                            $transparency[0] | $transparency[1] << 8 | $transparency[2] << 16 : -1;
        $this->_width     = $width;
        $this->_height    = $height;
    }

    /**
     * Add a frame to the animation
     *
     * @param string $data            The frame data which can be any image supported by GD provided GD is installed
     * @param int $duration            The duration of the frame
     * @param bool $resize            Resize the frame to the output width/height
     * @param int $xpos            The horizontal offset for the frame
     * @param int $ypos            The vertical offset for the frame
     * @param int $orDisposal        Override the global disposal setting for this frame
     * @param array $orTransparency    Override the global transparency setting for this frame
     */
    public function addFrame($data, $data2, $duration, $resize = false, $xpos = 0, $ypos = 0, $orDisposal = false, $orTransparency = true)
    {
        // Resize or convert the image if GD is enabled (also GD will notice any bad data)
        if (function_exists('gd_info')) {
            if ($resize) {
                $data = $this->_resizeImage($data,$data2);
            } else {
                $data = $this->_convertImage($data);
            }
        } else {
            // Verify the data looks like it is a gif image
            $header = substr($data, 0, 6);
            if ($header != 'GIF87a' && $header != 'GIF89a') {
                throw new Exception(self::VERSION . ' Error: Data does not appear to be a valid gif image.');
            }
            if (strstr($data, 'NETSCAPE') !== false) {
                throw new Exception(self::VERSION . ' Error: Animated gif frames are not currently supported.');
            }
        }
        // Populate global values form first frame
        if (!count($this->_global)) {
            $this->_defineGlobals($data);
        }
        // Define frame specific vars
        $locStr = 13 + 3 * (2 << ( ord($data{10}) & 0x07));
        $locEnd = strlen($data) - $locStr - 1;
        $locTmp = substr($data, $locStr, $locEnd);
        $locLen = 2 << (ord($data{10}) & 0x07);
        // Extract local colour pallet
        $locRGB = substr($data, 13, 3 * (2 << (ord($data{10}) & 0x07)));
        // Frame disposal override
        if ($orDisposal !== false) {
            $locDis = $orDisposal >= 0 && $orDisposal <= 3 ? $orDisposal : 2;
        } else {
            $locDis = $this->_disposal;
        }
        // Frame transparency override
        if ($orTransparency !== false) {
            $locCol = $orTransparency[0] > -1 || $orTransparency[1] > -1 || $orTransparency[2] > -1 ?
                      $orTransparency[0] | $orTransparency[1] << 8 | $orTransparency[2] << 16 : -1;
        } else {
            $locCol = $this->_colour;
        }
        // Look for transparent colour in the pallet
        if ($locCol > -1 && ord($data{10}) & 0x80) {
            for ($i = 0; $i < (2 << (ord($data{10}) & 0x07)); $i++) {
                if (ord($locRGB{3 * $i + 0}) == (($locCol >> 16) & 0xFF) &&
                    ord($locRGB{3 * $i + 1}) == (($locCol >> 8)  & 0xFF) &&
                    ord($locRGB{3 * $i + 2}) == (($locCol >> 0)  & 0xFF)) {
                    $locExt = "!\xF9\x04" . chr (($locDis << 2) + 1) . chr(($duration >> 0) & 0xFF) .
                              chr(($duration >> 8) & 0xFF) . chr($i) . "\x0";
                    break;
                }
            }
        }
        if (!isset($locExt)) {
            $locExt = "!\xF9\x04" . chr(($locDis << 2) + 0) . chr(($duration >> 0) & 0xFF) .
                      chr(($duration >> 8) & 0xFF) . "\x0\x0";
        }
        // Extract the image descriptor
        switch ($locTmp{0}) {
            case '!':
                $locImg = substr($locTmp, 8, 10);
                $locTmp = substr($locTmp, 18, strlen($locTmp) - 18);
                break;
            case ',':
                $locImg = substr($locTmp, 0, 10);
                $locTmp = substr($locTmp, 10, strlen($locTmp) - 10);
                break;
        }
        // Modify image position in image descriptor
        if ($xpos > 0) {
            $locImg{1} = chr($xpos & 0xff);
            $locImg{2} = chr(($xpos >> 8) & 0xFF);
        }
        if ($ypos > 0) {
            $locImg{3} = chr($ypos & 0xff);
            $locImg{4} = chr(($ypos >> 8) & 0xFF);
        }
        // Create frame
        $frame = '';
        if (ord($data{10}) & 0x80 && count($this->_frames)) {
            if ($this->_global['len'] == $locLen) {
                if ($this->_blockCompare($this->_global['rgb'], $locRGB, $locLen) ) {
                    $frame .= $locExt . $locImg . $locTmp;
                } else {
                    $byte  = ord($locImg{9});
                    $byte |= 0x80;
                    $byte &= 0xF8;
                    $byte |= ord($this->_global['frame']{10}) & 0x07;
                    $locImg{9} = chr($byte);
                    $frame .= $locExt . $locImg . $locRGB . $locTmp;
                }
            } else {
                $byte  = ord($locImg{9});
                $byte |= 0x80;
                $byte &= 0xF8;
                $byte |= ord($data{10}) & 0x07;
                $locImg{9} = chr($byte);
                $frame .= $locExt . $locImg . $locRGB . $locTmp;
            }
        } else {
            $frame .= $locExt . $locImg . $locTmp;
        }
        $this->_frames[] = $frame;
    }

    /**
     * Get the animation
     *
     * @return string
     */
    public function getAnimation(){
   
        return $this->_getHeader() . implode($this->_frames) . $this->_getFooter();
    }

    /**
     * Get animation header
     *
     * @return string
     */
    private function _getHeader()
    {
        if (!isset($this->_global['frame'])) {
            throw new Exception(self::VERSION . ' Error: A frame must be added before header can be generated.');
        }
        $header = self::GIF_HEADER;
        $cmap = 0;
        if (ord($this->_global['frame']{10}) & 0x80) {
            $cmap = 3 * ( 2 << (ord($this->_global['frame']{10}) & 0x07));
            $header .= substr($this->_global['frame'], 6, 7);
            $header .= substr($this->_global['frame'], 13, $cmap);
            $header .= "!\377\13NETSCAPE2.0\3\1" . $this->_word($this->_loops) . "\0";
        }
        return $header;
    }

    /**
     * Get animation footer
     *
     * @return string
     */
    private function _getFooter()
    {
        return ';';
    }

    /**
     * Resize image (using GD library)
     *
     * @param string $data
     * @return string
     */
    private function _resizeImage($data,$data2)
    {
        // Create image from data
        //$img = imagecreatefromstring($data);
        $img = imagecreatefrompng($data2);
        if (!$img) {
            throw new Exception(self::VERSION . ' Error: Image format is invalid or unsupported.');
        }
        if (imageistruecolor($img)) {
            $newImg = imagecreatetruecolor($this->_width, $this->_height);
           
            //$tran = imagecolortransparent($newImg, imagecolortransparent($img));
            //imagefill($newImg, 0, 0, $tran);
           
            //imagealphablending($img, false);
            //imagesavealpha($img, true);
            //$newImg = imagecreatetruecolor($this->_width, $this->_height);
            //imagealphablending($newImg, false);
            //imagesavealpha($newImg, true);
       
        } else {
            $newImg = imagecreate($this->_width, $this->_height);

        }
       

       
               
        // Resample
        imagecopyresampled($newImg, $img, 0, 0, 0, 0, $this->_width, $this->_height, imagesx($img), imagesy($img));
        imagedestroy($img);
        // Get image as gif
        ob_start();
       
        imagegif($newImg);
        $resImg = ob_get_contents();
        imagedestroy($newImg);
        ob_end_clean();
        return $resImg;
    }

    /**
     * Convert image to gif (using GD library)
     *
     * @param string $data
     * @return string
     */
    private function _convertImage($data)
    {
        // Create image from data
        $img = imagecreatefromstring($data);
        if (!$img) {
            throw new Exception(self::VERSION . ' Error: Image format is invalid or unsupported.');
        }
        // Get image as gif
        ob_start();
       
        imagegif($img);
        $resImg = ob_get_contents();
        imagedestroy($img);
        ob_end_clean();
        return $resImg;
    }

    /**
     * Get global params from the first frame
     *
     * @param string $data
     * @return void
     */
    private function _defineGlobals($data)
    {
        $this->_global['frame'] = $data;
        $this->_global['len']   = 2 << (ord($data{10}) & 0x07);
        $this->_global['rgb']   = substr($data, 13, 3 * (2 << (ord($data{10}) & 0x07)));
    }

    /**
     * Block comparism
     *
     * @param string $global
     * @param string $local
     * @param int $length
     * @return bool
     */
    private function _blockCompare($global, $local, $length)
    {
        for ($i = 0; $i < $length; $i++) {
            if ($global{3 * $i} != $local{3 * $i} ||
                $global{3 * $i + 1} != $local{3 * $i + 1} ||
                $global{3 * $i + 2} != $local{3 * $i + 2}) {
                return false;
            }
        }
        return true;
    }

    /**
     * Word
     *
     * @param int $int
     * @return string
     */
    private function _word($int)
    {
        return chr($int & 0xFF) . chr(($int >> 8) & 0xFF);
    }

}
Najpierw stwórzmy sobie nowy obiekt naszej klasy czyli np:
$gif = new gifcreator(1, 2, array(255, 255, 255), 66, 18);
W construct naszej klasy widzimy parametry a ciut wyżej ładnie zakomentowane informacje, które mówią za co dany atrybut odpowiada. W naszym przykładzie pierwszy parametr mówi, że pętla animacyjna będzie przechodziła tylko raz, następny argument "disposal" jest dosyć tajemniczy, można zrobić test z wartościami (od 0 do 3). Trzecim parametrem jest tablica z wartościami transparentnymi koloru, my mamy trzy 255 czyli kolor biały. Następnie dwie wartości - rozmiarówki width (szerokość) i height (długość).

Stworzenie anima

Obiekt mamy to zróbmy coś na nim. Z racji, że klasa pomaga w tworzeniu animacji skorzystamy z funkcji do skreowania naszego migającego obrazka za pomocą funkcji addFrame:

// Add each frame to the animation
$gif->addFrame(file_get_contents('../images/animacja/1.png'),'../images/animacja/docelowy.png', 45, true);
$gif->addFrame(file_get_contents('../images/animacja/2.png'),'../images/animacja/docelowy.png', 45, true);      // Output the animated gif

//header('Content-type: image/gif');
header('Content-type: image/gif');
echo $gif->getAnimation();
Co się dzieje w powyższym kodzie? Mamy przygotowane dwa statyczne obrazki 1.png i 2.png, które mają wejść w gifa i obrazek "puszka", tam ma być docelowy gif. Wywołujemy funkcję addFrame podając ścieżki do naszych statyków podając ścieżkę docelową  (docelowy.png) i ustalając czas przejścia pomiędzy klatkami. Finalnie dajemy headerka i echujemy naszego gifka ciesząc się z przechodzących klatek na obrazku.

czwartek, 3 kwietnia 2014

Mieszarka elementów w tablicy | JAVASCRIPT

Przedstawie krótkiego posta z gotową funkcją na czele, która miesza wartości w tablicy (w technologii Java Script)

Najpierw kod:

function mieszamy(tablica) {
    for (var i = 0; i < tablica.length; i++) { 

        var j = Math.floor(Math.random() * tablica.length);
        var temp = tablica[i]; 
        tablica[i] = tablica[j]; 
        tablica[j] = temp;
    }
    return tablica;
}
Nasz algorytm idzie w pętli for, przechodząc po kolei elementy tablicy. W środku losujemy wartość z przedziału od 0 do tablica.length-1 (dlatego minus 1 bo tablica idzie od indeksu "0") . Tworzymy zmienną tymczasową temp gdzie podstawiamy wartość obecnie literowanego indeksu. Następnie pod bieżący indeks podstawiamy wylosowaną wartość a pod wylosowany wartość z bieżącego indeksu i VUALA.