gd_gradient_fill Funktion, mit endlos langer Ladezeit

Matze202

Erfahrenes Mitglied
Hiho @all,

ich hoff, dass jemand den Fehler, der endlos langen Ladezeiten der folgenden Datei findet, wenn ich die Bedingungen der 1. bzw. der 2. IF-Schleife erfülle. Wenn ich jedoch keine der Bedingungen erfülle und dadurch den am Ende der Datei aufgeführten Code nutze, funktioniert das ganze problemlos.

PHP:
<?

require_once('./../gd-gradient-fill.php');

// Farbverläufe aus der Datenbank laden
if($_GET['site_color'] >= 1){
	include('./config.inc.php');
	$site_color = mysql_fetch_array(mysql_query("SELECT * FROM pl4u_bg_images WHERE id='".mysql_real_escape_string($_GET['site_color'])."'"));
	$width = $site_color['width'];
	$height = $site_color['height'];
	$direction = $site_color['direction'];
	$startcolor = "#".$site_color['startcolor'];
	$endcolor = "#".$site_color['endcolor'];
	$step = $site_color['step'];
	$image = new gd_gradient_fill($width,$height,$direction,$startcolor,$endcolor,$step);
	mysql_close();
	exit;
}

// Farbverläufe über $_GET beziehen
if($_GET['width'] >= 1 AND $_GET['height'] >= 1){
	$image = new gd_gradient_fill($_GET['width'],$_GET['height'],$_GET['direction'],"#".$_GET['startcolor'],"#".$_GET['endcolor'],$_GET['step']);
	exit;
}

$width = "1";
$height = "800";
$direction = "vertical"; 					// Zur Auswahl stehen: vertical, horizontal, ellipse, ellipse2, circle, circle2, rectangle, diamond
$startcolor = "#FFBC47";
$endcolor = "#FBFFC9";
$step = "0";
$image = new gd_gradient_fill($width,$height,$direction,$startcolor,$endcolor,$step);

?>

Hier mal noch die dazu gehörige Datei, welche ich nutze, um mehrfarbige Hintergründe zu erstellen. Diese Datei findet ihr auch im Anhang als Zip-Datei.

PHP:
<?php
/*
Script Name: GD Gradient Fill
Script URI: http://planetozh.com/blog/my-projects/images-php-gd-gradient-fill/
Description: Creates a gradient fill of any shape (rectangle, ellipse, vertical, horizontal, diamond)
Author: Ozh
Version: 1.1
Author URI: http://planetozh.com/
*/

/* Release history :
 * 1.1
 *        - changed : more nicely packaged as a class
 *        - fixed : not displaying proper gradient colors with image dimension greater than 255 (because of a limitation in imagecolorallocate)
 *        - added : optional parameter 'step', more options for 'direction'
 * 1.0
 *        - initial release
 */

/* Usage :
 *
 * require_once('/path/to/gd-gradient-fill.php');
 * $image = new gd_gradient_fill($width,$height,$direction,$startcolor,$endcolor,$step);
 *
 * Parameters :
 *        - width and height : integers, dimesions of your image.
 *        - direction : string, shape of the gradient.
 *          Can be : vertical, horizontal, rectangle (or square), ellipse, ellipse2, circle, circle2, diamond.
 *        - startcolor : string, start color in 3 or 6 digits hexadecimal.
 *        - endcolor : string, end color in 3 or 6 digits hexadecimal.
 *        - step : integer, optional, default to 0. Step that breaks the smooth blending effect.
 * Returns a resource identifier.
 *
 * Examples :
 *
 * 1.
 * require_once('/home/ozh/www/includes/gd-gradient-fill.php');
 * $image = new gd_gradient_fill(200,200,'horizontal','#fff','#f00');
 *
 * 2.
 * require_once('c:/iis/inet/include/gd-gradient-fill.php');
 * $myimg = new gd_gradient_fill(80,20,'diamond','#ff0010','#303060');
 *
 */


// Test it :
// $image = new gd_gradient_fill(400,200,'ellipse','#f00','#000',0);

class gd_gradient_fill {
    
    // Constructor. Creates, fills and returns an image
    function gd_gradient_fill($w,$h,$d,$s,$e,$step=0) {
        $this->width = $w;
        $this->height = $h;
        $this->direction = $d;
        $this->startcolor = $s;
        $this->endcolor = $e;
        $this->step = intval(abs($step));

        // Attempt to create a blank image in true colors, or a new palette based image if this fails
        if (function_exists('imagecreatetruecolor')) {
            $this->image = imagecreatetruecolor($this->width,$this->height);
        } elseif (function_exists('imagecreate')) {
            $this->image = imagecreate($this->width,$this->height);
        } else {
            die('Unable to create an image');
        }
        
        // Fill it
        $this->fill($this->image,$this->direction,$this->startcolor,$this->endcolor);
        
        // Show it        
        $this->display($this->image);
        
        // Return it
        return $this->image;
    }
    
    
    // Displays the image with a portable function that works with any file type
    // depending on your server software configuration
    function display ($im) {
        if (function_exists("imagepng")) {
            header("Content-type: image/png");
            imagepng($im);
        }
        elseif (function_exists("imagegif")) {
            header("Content-type: image/gif");
            imagegif($im);
        }
        elseif (function_exists("imagejpeg")) {
            header("Content-type: image/jpeg");
            imagejpeg($im, "", 0.5);
        }
        elseif (function_exists("imagewbmp")) {
            header("Content-type: image/vnd.wap.wbmp");
            imagewbmp($im);
        } else {
            die("Doh ! No graphical functions on this server ?");
        }
        return true;
    }
    
    
    // The main function that draws the gradient
    function fill($im,$direction,$start,$end) {
        
        switch($direction) {
            case 'horizontal':
                $line_numbers = imagesx($im);
                $line_width = imagesy($im);
                list($r1,$g1,$b1) = $this->hex2rgb($start);
                list($r2,$g2,$b2) = $this->hex2rgb($end);
                break;
            case 'vertical':
                $line_numbers = imagesy($im);
                $line_width = imagesx($im);
                list($r1,$g1,$b1) = $this->hex2rgb($start);
                list($r2,$g2,$b2) = $this->hex2rgb($end);
                break;
            case 'ellipse':
                $width = imagesx($im);
                $height = imagesy($im);
                $rh=$height>$width?1:$width/$height;
                $rw=$width>$height?1:$height/$width;
                $line_numbers = min($width,$height);
                $center_x = $width/2;
                $center_y = $height/2;
                list($r1,$g1,$b1) = $this->hex2rgb($end);
                list($r2,$g2,$b2) = $this->hex2rgb($start);
                imagefill($im, 0, 0, imagecolorallocate( $im, $r1, $g1, $b1 ));
                break;
            case 'ellipse2':
                $width = imagesx($im);
                $height = imagesy($im);
                $rh=$height>$width?1:$width/$height;
                $rw=$width>$height?1:$height/$width;
                $line_numbers = sqrt(pow($width,2)+pow($height,2));
                $center_x = $width/2;
                $center_y = $height/2;
                list($r1,$g1,$b1) = $this->hex2rgb($end);
                list($r2,$g2,$b2) = $this->hex2rgb($start);
                break;
            case 'circle':
                $width = imagesx($im);
                $height = imagesy($im);
                $line_numbers = sqrt(pow($width,2)+pow($height,2));
                $center_x = $width/2;
                $center_y = $height/2;
                $rh = $rw = 1;
                list($r1,$g1,$b1) = $this->hex2rgb($end);
                list($r2,$g2,$b2) = $this->hex2rgb($start);
                break;
            case 'circle2':
                $width = imagesx($im);
                $height = imagesy($im);
                $line_numbers = min($width,$height);
                $center_x = $width/2;
                $center_y = $height/2;
                $rh = $rw = 1;
                list($r1,$g1,$b1) = $this->hex2rgb($end);
                list($r2,$g2,$b2) = $this->hex2rgb($start);
                imagefill($im, 0, 0, imagecolorallocate( $im, $r1, $g1, $b1 ));
                break;
            case 'square':
            case 'rectangle':
                $width = imagesx($im);
                $height = imagesy($im);
                $line_numbers = max($width,$height)/2;
                list($r1,$g1,$b1) = $this->hex2rgb($end);
                list($r2,$g2,$b2) = $this->hex2rgb($start);
                break;
            case 'diamond':
                list($r1,$g1,$b1) = $this->hex2rgb($end);
                list($r2,$g2,$b2) = $this->hex2rgb($start);
                $width = imagesx($im);
                $height = imagesy($im);
                $rh=$height>$width?1:$width/$height;
                $rw=$width>$height?1:$height/$width;
                $line_numbers = min($width,$height);
                break;
            default:
        }
        
        for ( $i = 0; $i < $line_numbers; $i=$i+1+$this->step ) {
            // old values :
            $old_r=$r;
            $old_g=$g;
            $old_b=$b;
            // new values :
            $r = ( $r2 - $r1 != 0 ) ? intval( $r1 + ( $r2 - $r1 ) * ( $i / $line_numbers ) ): $r1;
            $g = ( $g2 - $g1 != 0 ) ? intval( $g1 + ( $g2 - $g1 ) * ( $i / $line_numbers ) ): $g1;
            $b = ( $b2 - $b1 != 0 ) ? intval( $b1 + ( $b2 - $b1 ) * ( $i / $line_numbers ) ): $b1;
            // if new values are really new ones, allocate a new color, otherwise reuse previous color.
            // There's a "feature" in imagecolorallocate that makes this function
            // always returns '-1' after 255 colors have been allocated in an image that was created with
            // imagecreate (everything works fine with imagecreatetruecolor)
            if ( "$old_r,$old_g,$old_b" != "$r,$g,$b") 
                $fill = imagecolorallocate( $im, $r, $g, $b );
            switch($direction) {
                case 'vertical':
                    imagefilledrectangle($im, 0, $i, $line_width, $i+$this->step, $fill);
                    break;
                case 'horizontal':
                    imagefilledrectangle( $im, $i, 0, $i+$this->step, $line_width, $fill );
                    break;
                case 'ellipse':
                case 'ellipse2':
                case 'circle':
                case 'circle2':
                    imagefilledellipse ($im,$center_x, $center_y, ($line_numbers-$i)*$rh, ($line_numbers-$i)*$rw,$fill);
                    break;
                case 'square':
                case 'rectangle':
                    imagefilledrectangle ($im,$i*$width/$height,$i*$height/$width,$width-($i*$width/$height), $height-($i*$height/$width),$fill);
                    break;
                case 'diamond':
                    imagefilledpolygon($im, array (
                        $width/2, $i*$rw-0.5*$height,
                        $i*$rh-0.5*$width, $height/2,
                        $width/2,1.5*$height-$i*$rw,
                        1.5*$width-$i*$rh, $height/2 ), 4, $fill);
                    break;
                default:    
            }        
        }
    }
    
    // #ff00ff -> array(255,0,255) or #f0f -> array(255,0,255)
    function hex2rgb($color) {
        $color = str_replace('#','',$color);
        $s = strlen($color) / 3;
        $rgb[]=hexdec(str_repeat(substr($color,0,$s),2/$s));
        $rgb[]=hexdec(str_repeat(substr($color,$s,$s),2/$s));
        $rgb[]=hexdec(str_repeat(substr($color,2*$s,$s),2/$s));
        return $rgb;
    }
}
?>

Gruß Matze.
 

Anhänge

Hallo,

das füllen eines Bildes (abhängig von der Größe; bei z.B. 1024x768px) dauert es (vor allem bei PHP, da das nicht so schnell ist) schonmal ein paar Sekunden, da dort 1024 * 768 = 786432 mal ein Pixel in dem Bild gefüllt wird.
Außerdem ist das sehr Server-lastig und sollte niemals bei jedem Seitenaufruf so aufgerufen werden.
Deswegen solltest du z.B. diese Bilder cachen (im Dateinamen für die gecachte Datei sollte aber jeder übergebene Parameter vorhanden sein, sonst werden manchmal falsche Bilder ausgegeben) und wenn ein gecachtes Bild vorhanden ist, das Bild includen und vorher natürlich noch den Content-Type in den Headern richtig setzen.

Dann sollte es auch keine Probleme mit der Ladezeit und der Server-Last geben ;)

MfG
Fabsch
 
Danke für deine Meinung, aber dies habe ich dann auch vor, wenn ich das jetzige Problem beseitigt habe.

Ich beschreibe das Problem nochmal neu:

1. Wenn ich keine der beiden IF-Schleifen-Bedingungen erfülle, ist das selbe generierte Bild, wie ich für die anderen beiden IF-Schleifen eingestellt habe problemlos binnen eines Bruchteils einer Sekunde.

2. Wenn ich die Bedingung der 1. IF-Schleife erfülle und die selben Daten wie bei 1. verwendet werden, wird der nicht fertig mit rechnen.

3. Die 2. IF-Schleife verhält sich analog zu der 2..

Vielleicht findet ja doch noch jemand den Fehler, sonst brauch ich mich garnicht an die weitere Anpassung mit der Abspeicherung der Grafiken usw. machen.

M.f.G. Matze202.
 
Nach den beiden If-Schleifen ist das Bild auch nur 1px breit und 800px hoch, also nur 800 Durchgänge, weswegen das auch nur weniger als eine Sekunde dauert.
Bei den beiden IF-Abfragen muss ich die Parameter wissen (vor allem width und height) die dort verwendet werden um das Bild zu erzeugen, da die Dauer zum Erzeugen des Bildes von diesen Parametern abhängt (vor allem width und height, da bei dem Bild dann nämlich width * height Pixel gesetzt werden müssen).
 
Hi Fabsch!

Ich habe bei dem testen 800 * 800 Pixel und die Farben von #000000 nach #FFFFFF gewählt.

Also voreingestellt in den Variablen, ist das Bild sofort da, aber voreingestellt in der Datenbank oder mit $_GET eingebunden, wird das Script leider nicht fertig.

Gruß Matze202.
 
Hallo Matze202,

wie wäre es denn, wenn du einfach das Bild zum Testen nimmst, dass du auch schon bei deiner Voreinstellung hast, damit kannst du schneller nachschauen, ob es am Code liegt oder ob es an der Größe der Grafik liegt, wie es schon Fabsch beschrieben hatte.


Gruß Nuddel
 
Hi @Nuddel!

Das hab ich doch gerade im letzten Post von mir beschrieben, dass ich dies bereits mehrfach gemacht habe,

Gruß Matze202.
 
Also Matze202,

dann hatte ich leider dein Post falsch gelesen, sorry nochmal. Ich habe jetzt mal einen kleinen Test gemacht.

Ich habe mir die Dateien runtergeladen und auf meinen Server hochgeladen. Ich werde auch noch mal weiter testen, besonders mit der Datenbank. Aber die zweite IF-Abfrage funktioniert mit der Übergabe der Parameter, so dass der Server, auch sehr schnell ohne lange Ladezeit, die man spürt das Bild errechnet und es aus gibt.

Wenn du es dir mal anschauen möchtest hier ist der Link: Mit den Parametern: "Länge auf 1024, Höhe bei 800, Richtigung ist Vertikal, die Startfrage ist Schwarz und die Entfrage ist weiß. Und Step wurde auf eins gesetzt."

Ich werde jetzt gleich noch mal eine Datenbank damit aufbauen und dies mit Werten füttern. Damit auch sichergestellt werden kann, dass er auch die If-Abfrage, für die Datenbank richtig erfüllt und korrekt abarbeitet.

Vielleicht ist dein Fehler irgendwo in der Übergabe der Werte, dass die Klasse veranlasst in einer Art Endlosschleife zusein, oder dass vielleich sogar dein Server, diese Klasse nicht richtig bzw 100%ig unterstützt.


Gruß
 
Zuletzt bearbeitet:
Das einzige eigentlich woran es noch liegen kann, ist die Datei config.inc.php.
Dort wird denke ich eine Datenbankverbindung aufgebaut.
Aber poste mal den gesamten Inhalt dieser Datei (Datenbank-Zugangsdaten natürlich vorher ändern ;) ).

Ansonsten werde ich das mal testen und schauen, woran das liegen könnte.
 
Sorry, aber ich komm leider heute erst wieder dazu, zu antworten.

@Nuddel:

Danke, irgendwie vermute ich, dass ich einen Schreibfehler in der $_POST-Adresszeileneingabe gehabt hatte. Dies ist warscheinlich auch in der DB der Fall.

@Fabsch:

Also hier noch die gewünschte config.inc.php

PHP:
<?php

// MySQL-Datenbanklogindaten
$mysql_login['host'] = "localhost";
$mysql_login['user'] = "db-xyz";
$mysql_login['pass'] = "db-passf";
$mysql_login['name'] = "db-name";

// MySQL-Datenbanklogin
mysql_connect ($mysql_login['host'], $mysql_login['user'], $mysql_login['pass'])or die(bug_mysql_connect);
mysql_select_db($mysql_login['name'])or die(bug_mysql_db_connect);

// Protokoll
$protokoll['http'] = "http://";
$protokoll['ssl'] = "https://";
$protokoll['ftp'] = "ftp://";

// Domains definieren
$domain['haupt'] = "*************";

// Templatepfad definieren
$pfad['template'] = $protokoll['http']."".$domain['haupt']."/templates/Standart/";

?>

Die Domain hab ich auch mal noch ersetzt, weil dieses Script noch nicht veröffentlicht werden soll. Wenn es fertig sein wird, findet ihr es irgendwann bestimmt hier in der Signatur.

Hier auch gleich mal noch der DB-Auszug für die verwendete Tabelle:

Code:
CREATE TABLE `pl4u_bg_images` (
  `id` int(11) NOT NULL auto_increment,
  `user_id` int(11) NOT NULL default '0',
  `width` int(4) NOT NULL default '0',
  `height` int(4) NOT NULL default '0',
  `direction` varchar(15) NOT NULL default '',
  `startcolor` varchar(8) NOT NULL default '',
  `endcolor` varchar(8) NOT NULL default '',
  `step` char(1) NOT NULL default '',
  PRIMARY KEY  (`id`)
) TYPE=MyISAM AUTO_INCREMENT=3 ;

--
-- Daten für Tabelle `pl4u_bg_images`
--

INSERT INTO `pl4u_bg_images` (`id`, `user_id`, `width`, `height`, `direction`, `startcolor`, `endcolor`, `step`) VALUES
(1, 1, 1, 800, 'vertical', 'FFBC47', 'FBFFC9', '0'),
(2, 1, 800, 800, 'diamond', '00000000', 'FFFFFFFF', '0');

Gruß Matze202.
 
Zurück