PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : dynamische Bild-Klasse richtig einbinden!



nul
09-02-2005, 15:16
Jungs, ich brauch eure Hilfe; ich hab mir ff. Klasse geschrieben um dynamisch Diagramme erzeugen zu koennen:

<?php
class Diagram {
var $xsize; /* Die Breite des Bildes. */
var $ysize; /* Die Hoehe des Bildes. */
var $spacer; /* Der freie Bereich zwischen Bildrahmen und Diagram. */
var $diagram_heigth; /* Die Hoehe des Diagrams ($ysize-$spacer). */
var $diagram_width; /* Die Breite des Diagrams ($xsize-$spacer). */
var $cell_width; /* Die Breite eines Balken. */
var $val_arr; /* Die Werte fuer das Diagram. */
var $name_arr; /* Die Bezeichnung fuer die Balken. */
var $image; /* Das Bild selber. */

/* Konstruktor. */
function Diagram($x, $y, $sp, $varr, $narr) {
$this->xsize = $x;
$this->ysize = $y;
$this->spacer = $sp;
$this->val_arr = $varr;
$this->name_arr = $narr;
$this->control();
}

/* Kontroll-Methode zur Kontrolle des Bildaufbaus. */
function control() {
$this->calcDiagramValues();
$this->calcValues();
$this->createImage();
}

/* Berechnet die Werte fuer das Diagram. */
function calcDiagramValues() {
$x = $this->xsize - ( 2*$this->spacer );
$y = $this->ysize - ( 2*$this->spacer );

if ( $x < 0 || $y < 0 ) {
echo "Values incorrect; x=$x, y=$y<br>\n";
exit();
} else {
$this->diagram_width = $x;
$this->diagram_heigth = $y;

/* Anzahl der Balken im Diagram. */
$num_values = count($this->val_arr);

if ( $num_values <= 0 ) {
echo "Division by zero value.";
exit();
}

/* Die Breite des Diagrams ohne den Abstand ($spacer/2*2) links und rechts. */
$width = $x - $this->spacer;
/* Der freie Bereich zwischen den Balken. */
$balc = ($num_values - 1) * (1/2) * $this->spacer;
/* Der noch verbleibende Platz fuer die Balken. */
$width = $width - $balc;
/* Zum Schluss wird noch die Breite eines Balkens berechnet. */
$this->cell_width = ($width/$num_values);

if ( $this->cell_width <= 0 ) {
echo "No space for the diagram-items: $this->cell_width.";
exit();
}
}
}

/* Legt den Hintergrund fuer das Bild fest. */
function setImageBackground() {
$bg = imagecolorallocate($this->image, 204, 204, 204);
}

/* Die Linien im Diagram. */
function setDiagramLines() {
$black = imagecolorallocate($this->image,0,0,0); /* Die Farbe fuer die Linien. */
imageline($this->image, $this->spacer, $this->spacer, $this->spacer, $this->ysize-$this->spacer, $black); // verticale Linie
imageline($this->image, $this->spacer, $this->ysize-$this->spacer, $this->xsize-$this->spacer, $this->ysize-$this->spacer, $black); // horizontale Linie
}

/* Zeichnet die Balken ins Diagram ein. */
function setDiagram() {
$colors = array(); /* Array der Farben fuer die Balken. */
$colors[count($colors)] = imagecolorallocate($this->image, 7,0,211);
$colors[count($colors)] = imagecolorallocate($this->image, 255,0,0);
$colors[count($colors)] = imagecolorallocate($this->image, 12, 255, 0);

$space = $this->spacer + (1/2)*$this->spacer;

for ( $counter = 0; $counter < count($this->val_arr); $counter++ ) {
$color = $colors[$counter%count($colors)]; /* Die Farbe fuer den aktuellen Wert/Balken. */
$value = $this->val_arr[$counter]; /* Den Wert fuer den aktuellen Balken. */

$firstPoint = array(); /* Der linke obere Punkt. */
$secondPoint = array(); /* Der rechte untere Punkt. */

$firstPoint[0] = $space;
$firstPoint[1] = $this->ysize - ($this->spacer + $value);

$secondPoint[0] = $space+$this->cell_width;
$secondPoint[1] = $this->ysize - $this->spacer -1;

imagefilledrectangle($this->image, $firstPoint[0], $firstPoint[1], $secondPoint[0], $secondPoint[1], $color);

$space += $this->cell_width + (1/2)*$this->spacer;
}
}

/* Zeigt noch die Bezeichnungen fuer die Balken an. */
function setNames() {
$black = imagecolorallocate($this->image,0,0,0); /* Die Farbe fuer den Text. */

$x = $this->spacer + (1/2)*$this->spacer + $this->cell_width * (1/2);
$y = $this->ysize - $this->spacer*(0.9);

for ( $counter = 0; $counter < count($this->name_arr); $counter++ ) {
$name = $this->name_arr[$counter];

imagestring($this->image, 2, $x-strlen($name), $y, $name, $black);
$x += $this->spacer*(1/2)+$this->cell_width;
}
}

/* Zeichne das Bild. */
function createImage() {
$this->image = imagecreate($this->xsize, $this->ysize);

$this->setImageBackground();
$this->setDiagramLines();
$this->setDiagram();
$this->setNames();

header('Content-type: image/png');
imagepng($this->image);
imagedestroy($this->image);
}

/* Finde den maximalen Wert im Array. */
function findMaxValue() {
$max = 0;
for ( $counter = 0; $counter < count($this->val_arr); $counter++ ) {
$value = $this->val_arr[$counter];
if ( $value > $max ) {
$max = $value;
}
}
return $max;
}

/* Berechne die Werte, damit sie ins Diagramm passen. */
function calcValues() {
$max = $this->findMaxValue();
for ( $counter = 0; $counter < count($this->val_arr); $counter++ ) {
$this->val_arr[$counter] = $this->diagram_heigth * $this->val_arr[$counter]/$max;
}
}
}
?>
Die Klasse funktioniert einwandfrei wenn man die TestSeite wie ff. schreibt:

<?php include("../statistic/Diagram.php");
$arr = array();
$arr[count($arr)] = 4;
$arr[count($arr)] = 2;
$x = 200;
$y = 400;
$s = 15;
$a = array();
$a[0] = "blau";
$a[1] = "rot";

new Diagram($x,$y,$s,$arr,$a);
?>
Wenn ich aber nun einen HTML-Header dazu bringe wie hier:

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title>Main Site</title>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<?php include("../statistic/Diagram.php");
$arr = array();
$arr[count($arr)] = 4;
$arr[count($arr)] = 2;
$x = 200;
$y = 400;
$s = 15;
$a = array();
$a[0] = "blau";
$a[1] = "rot";

new Diagram($x,$y,$s,$arr,$a);
?>
</body>
</html>
erhalte ich ff. Fehlermeldung:

Warning: Cannot modify header information - headers already sent by (output started at /var/www/include/tests/diaTest2.php:7) in /var/www/include/statistic/Diagram.php on line 130
‰PNG 
Wie kann ich ein Bild anzeigen, ohne dass ich eine zweite Datei erzeugen muss, in der die Werte stehn?

Vielleicht hat jemand eine Hilfreiche Idee!!!

mfg nul

Gaert
09-02-2005, 15:25
Hallo nul,

du hast einen kleinen Denkfehler gemacht...

Du musst dein PHP Skript mit "Content-type: image/png" über einen <img /> in deine HTML Seite einbetten - eine Ausgabe des Bilds direkt in das HTML kann nicht funktionieren.

Zu Erläuterung der Fehlermeldung -> http://php.net/header


Remember that header() must be called before any actual output is sent, either by normal HTML tags, blank lines in a file, or from PHP. It is a very common error to read code with include(), or require(), functions, or another file access function, and have spaces or empty lines that are output before header() is called. The same problem exists when using a single PHP/HTML file.

Gruß,

Gaert

nul
09-02-2005, 15:53
Ich finds aber eben unschoen, wenn ich zu jedem Bild eine eigene Datei machen muss; so z.B.:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Main Site</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<?php include("../statistic/Diagram.php"); ?>
<img src='pic.php'></img>
</body>
</html>
und

<?php include("../statistic/Diagram.php");
$arr = array();
$arr[count($arr)] = 4;
$arr[count($arr)] = 2;
$x = 200;
$y = 400;
$s = 15;
$a = array();
$a[0] = "blau";
$a[1] = "rot";

new Diagram($x,$y,$s,$arr,$a);
?>
Ich finde, dann ist der ganze Vorteil der dynamischen Klasse futsch.
Und wenn ich es so mache:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Main Site</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<?php include("../statistic/Diagram.php");
$arr = array();
$arr[count($arr)] = 4;
$arr[count($arr)] = 2;
$x = 200;
$y = 400;
$s = 15;
$a = array();
$a[0] = "blau";
$a[1] = "rot";
?>
<img src='<?php new Diagram($x,$y,$s,$arr,$a); ?>'></img>
</body>
</html>
erscheint bei mir eben kein Bild, nur das kleine Quadratische Bild-Icon.
Machen wollte ich es eben so wie der letzte Code-Abschnitt, das funktioniert aber nicht :( :mad: :( Und warum ist mir auch nicht klar!

mfg nul

Gaert
09-02-2005, 17:43
Machen wollte ich es eben so wie der letzte Code-Abschnitt, das funktioniert aber nicht :( :mad: :( Und warum ist mir auch nicht klar!

mfg nul

:eek: Weil das was du da machst quatsch ist, der nicht funktionieren kann!

Nochmal: Du kannst ein Bild nich als Binärdaten in eine HTML Datei einbetten... das geht per Definition NICHT!

Du musst ein Bild IMMER extern referenzieren mit:
<img src="bilddatei" />

Du kommst also nicht drum rum, dein Diagramm in einer extra Datei diagramm.php dynamisch zu erstellen und dann mit
<img src="diagramm.php" /> darauf zuzugreifen!

PS: Abgesehen davon - das include bei deinem ersten Beispiel kannst du dir sparen und wo sollte denn bitte der Vorteil sein, wenn du alles in eine Datei Packst???

nul
09-02-2005, 17:55
Der Vorteil wuerde darin liegen, dass ich keine Bild-Dateien anlegen muss - Die Klasse selber haette reichen sollen. Da das aber nicht geht muss ich mir ca. 200-230 Bild-Dateien erzeugen und diese dann Referenzieren.
Naja, umstaendlich, aber hauptsache es funkt!

Danke nochmal fuer deine Muehe!

mfg nul

msi
09-02-2005, 18:40
wieso benutzt du nicht GET um die entspr. werte an die php datei, die das bild erzeugt zu übergeben??

Pingu
09-02-2005, 18:53
Hi nul,

wie Gaert es schon versucht hat anzudeuten: Dies ist kein PHP-Problem. Du hast scheinbar die funktionsweise von HTML in Verbindung mit Bildern nicht richtig verstanden. Deiner Logik folgend, müßte es möglich sein direkt ein Bild in eine HTML-Datei zu integrieren. Das ging noch nie und wird nie gehen. Da HTML-Dateien keine Binär-Dateien sind. Bilder können über das sogenannte Tag <img> nur referenziert werden.

Daß die eigentlich HTML-Datei und das eigentliche Bild bei Dir mit Hilfe von PHP dynamisch erzeugt werden soll, ändert nichts an der Grundlegendenstruktur von HTML und sind zwei komplett verschiedene Dinge.
Dies hat nichts mit der Verwendung von Klassen zu tun. Klassen sind nur ein programmatisches Hilfsmittel, um zukünftige Arbeiten zu vereinfachen.

Für die Lösung Deines Problems mußt Du nicht vorher die Bilder erzeugen. Es ist eine Möglichkeit. Ein andere Möglichkeit ist, das Bild mit Hilfe von Parameter zu spezifizieren: <img src="/diagram.php?type=rund&groesse=irgendwas&und=soweiter"> Also im Grunde die Parameter, die Du normallerweise an Dein bisheriges PHP-Skript übergibst einfach an das PHP-Skript geben, welches für das Bild/Diagramm und allein das Diagramm und nichts anderes zuständig ist.

Pingu

nul
10-02-2005, 09:51
<img src="/diagram.php?type=rund&groesse=irgendwas&und=soweiter">

Genau sowas bin ich auch gerade beim Probieren, scheitere aber bei der Uebergabe der Arrays. Die kann man nicht als Parameter uebergeben (waehre mir halt neu).
Bin gerade beim googeln!!

mfg nul

Gaert
10-02-2005, 10:08
Du hast zwei Möglichkeiten:

1. Du übergibst die Werte einzeln

2. Du serialisierst dein Array für die Übergabe:

http://php.net/serialize
http://php.net/unserialize

Sicherheitshalber solltest du nach der Serialisierung noch ein urlencode() darüberlaufen lassen.

http://php.net/urlencode
http://php.net/urldecode


Da könntest du aber per GET Probleme bekommen falls die Arrays sehr groß sind.

Gruß,

Gaert

Pingu
10-02-2005, 10:21
Oder eine dritte Variante wäre (wenn die URL zu groß wird (Zeichenbegrenzung = 255)) das Ganze mit Hilfe von Sessions (http://www.php.net/session) zu realisieren und sich hierbei das Array in der Session merken.

Pingu

nul
10-02-2005, 10:51
Der String wird tatsaechlich etwas lang, ein Array mit 3 Werten sieht mit serialize und urldecode so aus:

a%3A3%3A%7Bi%3A0%3Bs%3A3%3A%22all%22%3Bi%3A1%3Bs%3 A4%3A%22seen%22%3Bi%3A2%3Bs%3A8%3A%22not+seen%22%3 B%7D
Naja, es funktioniert. Das mit der Session werd ich mir ueberlegen, find ich eigentlich recht sinnvoll. Mal sehn...
Auf jedenfall erst mal Danke fuer eure Hilfe!!!

mfg nul