Warnung: file_put_contents(/home/www/web1/html/php_dev/test.txt) [function.file-put-contents]: failed to open stream: Permission denied in /home/www/web1/html/php_dev/sys/lib.activity.php (Zeile 58)
"image2string" [Archiv] - PHP-Scripte PHP-Tutorials PHP-Jobs und vieles mehr

- Ad -
php-resource




Archiv verlassen und diese Seite im Standarddesign anzeigen :
"image2string"


 
Winner
30-07-2005, 17:48 
 
Hi,

ich will die Thumbs, die ich von Bildern erstelle in einer Datenbank speichern.
Jetzt kommt die spannende Frage: wie kann ich das verkleinerte Bild in einen Sting packen?

Das Bild ist ja bisher in der Resource id #x gespeichert.
Wie komm ich jetzt aber wirklich an den Inhalt ran?

 
wahsaga
30-07-2005, 18:08 
 
image(jpeg|png|gif)

vor diesen befehlen das output buffering anschalten, und anschließend bufferinhalt in variable holen (http://www.php.net/manual/de/ref.outcontrol.php).

 
Winner
30-07-2005, 18:24 
 
perfekt.

Danke

 
onemorenerd
30-07-2005, 22:02 
 
Darf man fragen, warum du nicht nur die URL der Bilder in der DB speicherst und die Bilder selbst als Dateien? So könnte sie der Webserver direkt ausliefern, ohne den Umweg über ein PHP-Script, das wiederum den Umweg über die DB nehmen muß.

 
Winner
31-07-2005, 11:05 
 
Punkt 1: wesentlich schneller

Punkt 2: ich will Kontrolle darüber haben wer, wann, wie oft auf di Bilder zugreift und die verkleinerten Bilder nach einer Zeit löschen, wenn sie nicht genutzt werden.

Punkt 3: Egal wo ich die Dateien ablege, muss ich immer die DB abfragen, da die Adresse der Thumbs in der Datenbank gespeichert werden.

[Dein Weg]

- Datenbank abfragen, ob Bild vorhanden ist

Wenn nicht vorhanden {
- Bild erstellen
- Bild in Datenbank eintragen
}else{
- Bild aus Datei auslesen
}
- Bild ausgeben
[/Dein Weg]

[Mein Weg]
- Datenbank abfragen, ob Bild vorhanden ist

Wenn nicht vorhanden {
- Bild erstellen
- Bild in Datenbank eintragen
}

- Bild ausgeben
[/Mein Weg]

ich spar mir also das auslesen aus der Datei, wobei ein Datenbankzugriff immer schneller ist als ein Dateizugriff.

 
onemorenerd
31-07-2005, 12:59 
 
[Dein Weg]
- Datenbank abfragen, ob Bild vorhanden ist
Wenn nicht vorhanden {
- Bild erstellen
- Bild in Datenbank eintragen
}else{
- Bild aus Datei auslesen
}
- Bild ausgeben
[/Dein Weg]

Nene, mein Weg wäre:
- DB abfragen
- Ergebnis (URL) an den Browser ausgeben

Ob dein Weg schneller ist, wäre noch zu beweisen.

 
penizillin
31-07-2005, 13:50 
 
Punkt 1: wesentlich schneller $skepsis = true;

gibt's dazu messergebnisse?

 
Winner
31-07-2005, 16:41 
 
if(true==$skepsis){

print time_function('image_thumb_filebased', $a_params);
print "\n";
print time_function('image_thumb_mysqlbased', $a_params);

}


Ausgabe (Mittelwert 10facher Ausführung):

0.163s
0.055s

 
penizillin
31-07-2005, 16:44 
 
keine schlechte idee, nur fehlt mir noch der quellcode von image_thumb_filebased() und image_thumb_mysqlbased(). wobei ich ersteres gern selbst vorbereiten würde.

aber zeig mir u.a. deine lösung.

 
Winner
31-07-2005, 16:51 
 
Das wird jetzt eine witzige Schnitzeljagt durch meine Bibilotheken :)

Das ist so verwurzelt in meinen Bibliotheken, dass es fast unmöglich wird da alle betreffenden Funktionen rauszufischen.

Wenn ich heute Abend daheim bin und Zeit finde schreibe ich vielleicht mal eine Funktion, die auf keine Bibilothek basiert.

Aber hier ist trotzdem mal der QT des eigentlichen Skriptes:

<?PHP
require_once("../config/config.initialization.php");
require_once(LIB_DIR."lib.image.php");
require_once(LIB_DIR."lib.file.php");

$b_border=($_GET['border']=='true')
? true
: false;

$b_fixed=($_GET['fixed']=='true')
? true
: false;
/**
* Prüfe, ob das Bild in dieser Größe schon mal verkleinert wurde
*/

$s_cached_pic=get_cached_image(
$_GET['img'],
$_GET['height'],
$_GET['width'],
$b_fixed,
$b_border,
$c_sql);

if(!empty($s_cached_pic)){
$r_img=imagecreatefromstring($s_cached_pic);
imagepng($r_img);
unset($r_img);


}else{

ob_start();
/**
* Speiche den Pfad zum Bild in Mysql
*/


image_resize(DOCUMENT_ROOT.$_GET['img'], true, $_GET['height'], $_GET['width'], $b_fixed, $b_border);

$bi_image=ob_get_contents();
ob_end_flush();

insert_cached_image(
$_GET['img'],
$_GET['width'],
$_GET['height'],
$b_fixed,
$b_border,
$bi_image,
$c_sql);
}
?>


Bin mal gespannt auf den evtl. Timing-Contest :)

 
penizillin
31-07-2005, 17:24 
 
unglaublich. habe es eben lokal selbst getestet.

meine und onemorenerds methode (mysql -> varchar -> echo '<img...'):
zwischen 245 und 270 ms pro aufruf

deine methode (mysql -> blob -> header -> echo):
zwischen 0,16 und 0,18 ms pro aufruf (!)

das ist in der tat ca. 1500 mal schneller.
experimentiert mit dem php-logo (ca. 4,5 kb) und einem foto (453 kb).

vermutlich wird der faktor 1500 schnell sinken, wenn die tabelle größer wird.viel zu übertrieben, weiter unten aktualisierung.

 
Winner
31-07-2005, 17:32 
 
Entweder Dein Rechner ist schneller als mein Pentium 2 Webserver *g*, oder eine der Funktionen passt nicht.

Wenn bei mir das Einlesen der Datei und das anschließende ausgeben 0,163 Sekunden braucht und das direkte Ausgeben aus der DB 0,055 Sekunden, dann deckt sich das nicht wirklich mit deinen Ergebnissen.

==> Entweder meine Mysql-Klasse ist verdammt langsam, oder Du hast beim Auslesen der Bilddatei irgendwie was verdreht... *grübel*



Was gibt es für Möglichkeiten das Bild zu lesen und auszugeben?

1.
header
print file_get_contents(..)

2.
imagecreatefrompng(...)
imagepng(...)

3
$r_file=fopen(...)
imagecreatefromstring(freads(...))
flose(...)
imagepng(...)


....

Theoretisch müsste die dritte die schnellste sein, aber auch nur theoretisch.

 
penizillin
31-07-2005, 17:45 
 
CREATE TABLE `test` (
`wert` varchar(10) default NULL,
`test` blob
) TYPE=MyISAM;

mein weg: //banale direkte verbindung zur db

$query = "SELECT `wert` FROM `test`";
$result = mysql_query($query);

$row = mysql_fetch_assoc($result);
echo "<img src='".$row['wert']."' />"

dein weg: //banale direkte verbindung zur db

$query = "SELECT `test` FROM `test`";
$result = mysql_query($query);

$row = mysql_fetch_assoc($result);

header('Content-Type: image/gif');
echo $row['test'];

zum messen wurde das beispiel aus der microtime() doku genommen.
habe die messungen etwas nachgebessert.

db: ca. 0,16 ms
fs: ca. 1,4 ms

also faktor ca. 8,75

 
penizillin
31-07-2005, 18:17 
 
noch mal edit:

habe einen fehler in der art gemacht, wie ich teste.
korrigiert.

die db gefüllt (1666 einträge, ca. 7,7 mb in der tabelle).

noch mal getestet. diesmal durchschnitt aus 100 durchläufen.

mein weg: 58 ms
dein weg: 59 ms

gleichstand?

 
Winner
01-08-2005, 08:17 
 
Moment!


Das Verhältnis der Ausführungszeiten ist in diesem Fall nicht gleich dem Verhältnis der Wartezeit für den Benutzer.


Teste das ganze mal mit ab von apache.

Bei deiner Möglichkeit muss Apache die Datei erst wieder öffnen und ausgeben. Bei meiner Möglichkeit ist das schon passiert.

PS. Wie ist der Aufbau deiner Mysql-Tabelle? Ich habe rund 600 MB in der Datenbank und die Anfragen sind unwesentlich langsamer als wie bei einer leeren Datenbank.

Ich habe eben einen Index auf das ID Feld und suche nur nach der ID

 
Quetschi
01-08-2005, 10:10 
 
Hallo,

klink mich hier mal ein, obwohl ich grad nicht wirklich aktiv was dazu beisteuern kann, mich interessiert es einfach.

Nur mal ein Gedanke noch dazu:
Die Ausführungszeit mag via DB gleich oder vielleicht sogar schneller sein - nur - wie sieht's mit der Auslastung von Prozessor und RAM aus? Ohne mir das ganze genau überlegt zu haben, würd ich doch tippen dass die DB-Lösung hier mehr Resourcen verbraucht.

Gruss
Quetschi

 
Winner
01-08-2005, 10:35 
 
Ich will Dir ja nicht auf die Füße treten, aber mein Mentor würde jetzt sagen: "Der werte Herr Mattes stellt eine Theorie auf. Nein Theorie kann man das nicht nennen...."

Wieso sollte das mehr Resourcen kosten?

Wenn Du eine Begründung bringst kann ich das mal kontrollieren, aber das kostet mich auch wertvolle Arbeitszeit.

 
Quetschi
01-08-2005, 10:50 
 
*Sicherheitsschuhe-anzieh*
nene, der Herr Mattes wollte keinen Theorie aufstellen ;)

Hab da nur einen Gedanken kurz verfolgt, der da grad in meinem Kopf auftauchte. Der Gedanke:
Das Bild wird ja in den RAM-Speicher des Servers geladen, da es ja in eine Var/Array oder was auch immer gebracht werden muss. Ohne genauer nachzudenken glaubte ich, dass das bei der Link-zur-Datei-Methode nicht der Fall wäre, was sich bei näherer Betrachtung natürlich eh als Unsinn entpuppt hat - oder schickt der Apache vielleicht doch das Bild direkt von der Festplatte an die Netzwerkkarte? :D

Gruss
Quetschi

 
penizillin
01-08-2005, 15:46 
 
hab kein ab, weil ich lokal iis nutze.

meine tabelle (3400 einträge, ca. 37 mb) CREATE TABLE `test` (
`id` int(10) unsigned NOT NULL auto_increment,
`filename` varchar(255) default NULL, /* hier dateiname */
`binfile` blob, /* hier binäre daten*/
`txtfile` mediumtext, /* hier binäre daten in base64 */
PRIMARY KEY (`id`) /* damit's schneller geht */
) TYPE=MyISAM;

wenn man davon ausgeht, dass die übermittlungsdauer vom server an den client egal ist (da sie ja immer von der anschlußgeschwindigkeit des users abhängt, etc.), interessiert mich nur die zeit, in der mein script abgearbeitet wird, sprich, die daten aus der db holt und sie übermittlungsbereit präsentiert.

d.h.

#1 $query = "SELECT `filename` AS `ausgabe` FROM `test` WHERE `id` = 1";
$result = mysql_query($query);
$row = mysql_fetch_assoc($result);

echo "<img src='".($row['ausgabe'])."' />";

#2 $query = "SELECT `binfile` AS `ausgabe` FROM `test` WHERE `id` = 1";
$result = mysql_query($query);
$row = mysql_fetch_assoc($result);

header('Content-Type: image/gif');
echo $row['ausgabe'];

#3 $query = "SELECT `txtfile` AS `ausgabe` FROM `test` WHERE `id` = 1";
$result = mysql_query($query);
$row = mysql_fetch_assoc($result);

header('Content-Type: image/gif');
echo base64_decode($row['ausgabe']);

damit ein wiederholtes testen möglich ist (1000 aufrufe), nutze ich output buffering, weil mich die ausgabe nicht interessiert.

in jedem der 3 fälle sind die daten ausgabebereit - apache muss nur noch die daten an den user übermitteln. die letzteren 2 methoden brauchen definitiv mehr speicher, weil $row['ausgabe'] jeweils 4,5 kb groß ist, während im ersten fall nur 7 byte benötigt werden.

ergebnis: filename: 1.6016 ms
binfile: 2.3162 ms
txtfile: 2.8832 ms

------------------------------------

Bei deiner Möglichkeit muss Apache die Datei erst wieder öffnen und ausgeben. Bei meiner Möglichkeit ist das schon passiert. ausgeben muss der server die daten bei jeder methode. das öffnen ist tatsächlich ein unterschied - da werd ich gleich mal noch eine runde testen. aber ich hab ja noch 0,7 ms in reserve :)


Alle Zeitangaben in WEZ +2. Es ist jetzt 17:29 Uhr.