Fatal error: Allowed memory size

Hallo zusammen
hab mir ein php zusammengebastelt (z.B. für Fotogalerien), dass mir grosse Bilder auf thumbnails verkleinert, um die ladezeit der Vorschauseite zu verkürzen. Nun habe ich aber ein jpeg-Bild auf A3-Grösse mit ca. 2MB, bei dem folgende Fehlermeldung erscheint:

hier die entsprechende Datei, um die Thumbnails herzustellen:

[code]<?php

if (isset($_GET[‘img’]) AND $_GET[‘img’] != ‘’)
{
$bilddatei = htmlspecialchars($_GET[‘img’]);

if (isset($_GET[‘quer_width’]) AND intval($_GET[‘quer_width’]))
{
$widthA = intval($_GET[‘quer_width’]);
}
else
{
die(‘Parameter Quer Width fehlt’);
}

if (isset($_GET[‘hoch_height’]) AND intval($_GET[‘hoch_height’]))
{
$heightA = intval($_GET[‘hoch_height’]);
}
else
{
die(‘Parameter Hoch Height fehlt’);
}

if (file_exists($bilddatei))
{
$imagetyp = getimagesize($bilddatei);
if ($imagetyp[2] == 1)
{
$imagedata = imagecreatefromgif($bilddatei);
$mimetype = “image/gif”;
}
if ($imagetyp[2] == 2)
{
$imagedata = imagecreatefromjpeg($bilddatei); // <== Zeile 37
$mimetype = “image/jpeg”;
}
if ($imagetyp[2] == 3)
{
$imagedata = imagecreatefrompng($bilddatei);
$mimetype = “image/png”;
}

 $imgOld= $imagedata;
 $imageInfo = getimagesize($bilddatei);
 $width = $imageInfo[0];
 $height = $imageInfo[1];
 
 if($width >= $height)
  {
  
   if ($width > $widthA) // Bild nur verkleinern, nicht vergroessern
   {
     $scale   = $widthA/$width;
     $heightA = round($height * $scale);
     $img = imagecreatetruecolor($widthA,$heightA);
     imagecopyresampled($img, $imgOld, 0,0, 0,0, $widthA,$heightA, ImageSX($imgOld),ImageSY($imgOld));
   } 
   else
   { $img = $imgOld; }
   
  }
  else
  {
  
   if ($height > $heightA) // Bild nur verkleinern, nicht vergroessern
   {
     $scale    = $heightA/$height;
     $widthA   = round($width * $scale);
     $img = ImageCreateTruecolor($widthA,$heightA);
     ImageCopyResampled($img, $imgOld, 0,0, 0,0, $widthA,$heightA, ImageSX($imgOld),ImageSY($imgOld));
   }
   else
   { $img = $imgOld; }
   
  }
  
header("Content-type: " . $mimetype);
if ($imagetyp[2] == 1)
{
 imagegif($img);
 imagedestroy($img);
}
if ($imagetyp[2] == 2)
{
 imagejpeg($img,NULL,100);
 imagedestroy($img);
}
if ($imagetyp[2] == 3)
{
 imagepng($img);
 imagedestroy($img);
}

}
else
{
echo(‘Datei existiert nicht’);
}
}
else
{
echo(‘Fehlender Parameter’);
}

?>[/code]

Das seltsame finde ich, dass der Speicher - wenn ich das richtig verstehe - auf 67MB eingestellt ist, aber die Datei, die ich verarbeiten möchte, nur 2MB gross ist.

Kann mir jemand erklären, wieso ich diesen Fehler erhalte…?

Vielen Dank schon mal
grüsse
samo

[quote]Kann mir jemand erklären, wieso ich diesen Fehler erhalte…?
[/quote]

klar, zuwenig Speicher :smiley:
ok, ganz im Ernst. Wie Dateigrösse eines JPG ist zweitrangig, es kommt auf die Abmessungen an, da die JPGs im Speicher des Rechner zu einer unkomprimierten Bitmap “entpackt” werden. Das bedeutet, dass ein einfarbiges Bild von 30002000 Pixeln als DATEI signifikant kleiner ist, als ein buntes Bild von 1000500 Pixeln, im Speicher wird es trotzdem 6 MAL soviel RAM verbraten, weil da die Abmessungen zählen und nicht wie gut sich das Bild als JPG hat packen lassen.

A3 ohne dpi Angabe sagt gar nichts aus, Aber wenn wir mal von A3 mit 200 DPI ausgehen, kommen wir da auf ein Bild das von den Abmessungen her aus einer 8MP Kamera stammen könnte … und ja, da wird es bei 64MB Ram für das entpackte Bild arg eng oder je nach Auslastung des Servers auch einfach nur unmöglich (die 64MB sind ja kein Garantiewert der auch noch eingehalten werden kann, wenn gerade 1000 User online sind,nä).

aha, vielen dank snafu, klingt plausibel…

kenst du ev. eine möglichkeit herauszufinden, wie gross eine Bild beim “entpacken” wird, um solche Fälle abzufangen…?
lg

das sollte sich anhand der Abmessungen herauskriegen lassen.

de2.php.net/manual/de/function.getimagesize.php

Genau kann ich dir das aber nicht sagen. Kommt drauf an wieviel Bits du pro Pixel brauchst :wink:
Zur Not musst du dann halt das ganze Bild runterladen lassen, und vom Browser skalieren lassen… :unamused:

BTW: Ich glaube solche Thumbnail-Scripts sind auf bplaced wegen der hohen Serverlast nicht erlaubt. Siehe AGB und den festgepinnten Fred unter Support

ich bin ja kein Programmierer und natürlich wird es sicher so eine Möglichkeit geben, wobei ich als Noob mich da in der angewandten Praxis der Hilfe eines scriptes bediene, dass ganz einfach unterschiedlich grosse Bilder abarbeitet und mir dann vermeldet bei welcher Bildgrösse der Server ausgestiegen ist.
Wobei das natürlich keine absolute Sicherheit gibt, weil, wie schon oben erwähnt, keine Garantie dafür hat, dass die 64MB die z.B. in der max_memory drinstehen, jetzt auch tatsächlich verfügbar sind. In der Praxis bedeutet dass, dass ein Testdurchlauf nachts um 03h problemlos durchgeht, während der Einsatz um 14 Uhr auf einem stark frequentierten Server mit viel Benutzern nur leise vor sich hinstirbt.

wenn dem so wäre, könnte man auf bplaced KEIN Galeriescript, egalob standalone oder als Teil von Joomla oder Wordpress hosten.
Was hier sicher verboten ist, sind thumbnailscripte die die Thumbs immer wieder von neuem on the fly generieren, etwas was inzwischen kein halbwegs passables galleriescript mehr macht, die generieren einmal und haben dann die Thumbs in einem entsprechenden Verzeichniss vorrätig.

Es gibt da einen EDIT-Button… :unamused:

Ich meintre solche Scripte, die es imer von neuem machen :wink:

Vielen Dank für eure Antworten!

Sehe ich das richtig, dass ich die “entpackte” grösse folgendermassen herausfinden kann:
Bild mit 3508x4962 Pixel und 24bit:
(3508 x 4962 x 24) / 8 = 52220088 byte = 52 MB
??

Klingt für mich logisch, ja :wink:
Du musst eben nur wissen, wieviel Bit du in der Grafik hast.
Ich bin mir da aber nicht sicher, kenn mich mit der Speicherung von Grafiken nicht so aus :wink:
Du musst auch bedenken, das da sicher noch was für headerinfos etc drauf kommt :wink:

Ja klar, muss man grosszügig rechnen :wink:
wobei warscheinlich die header-infos nicht allzuviel sein werden, aber egal…
und wie ihr schon sagtet, werden wohl nicht die ganzen 64MB zur verfügung stehen. Dies zeigt auch mein Beispiel: Das Bild hätte 52MB, der Speicher ist 64MB, und trotzdem gibts eine Fehlermeldung…

Die 52MB belegt das Bild alleine, da wurde noch kein einziger Bildpunkt mit den Grafikfunktionen bearbeitet (skaliert), was auch noch zusätzlichen Speicher benötigt.

Für die Bearbeitung bleiben dann nur noch die 12MB, in denen muss aber auch noch das neu erzeugte Bild Platz finden.

Alles zusammen dann doch recht mikrig, wenn man bedenkt wieviel Speicher Bildbearbeitung im Allgemeinen benötigt.

ouu, was da nicht alles dazu kommt…
hat jemand eine idee, wie viel der (angenommen ich hätte alles zur Verfügung) 64MB ich mit dem Original-Bild füllen darf, damit noch genug für den Rest übrig bleibt…?

Ich würde mal sagen maximal die Hälfte, also weniger als 32MB.

Mittels
$imgOld= $imagedata;
legst du das Bild ja sogar zweimal ab, also 2*52MB + Speicher
für neues Bild, das Originalbild braucht man aber nur einmal.

Ob das wirklich 52MB sind und was da noch für die
Bildbeabeitung gebraucht wird, hängt auch etwas vom internen
Format der gd ab.
Bei Pixelgraphik wird die Datei nicht größer, wenn man
darin irgendwas malt, zumindest sofern da keine zusätzlichen
’layer’ verwendet werden.

Bei sehr großen Bildern ist es einfach viel sinnvoller, die
Vorschaubilder auf dem eigenen Rechner berechnen zu lassen
als auf dem server. Sofern man dafür unbedingt PHP verwenden
will, kann man apache+PHP auf dem eigenen Rechner ja so
konfigurieren, daß genug Speicher vorhanden ist.

[quote]Mittels
$imgOld= $imagedata;
legst du das Bild ja sogar zweimal ab, also 2*52MB + Speicher
für neues Bild, das Originalbild braucht man aber nur einmal.[/quote]
Das ist das Problem an PHP, dass auch ein Zeiger auf ein Objekt das ganze Objekt kopieren muss, damit die Einfachheit von PHP erhalten bleibt…

Dateizugriff wie unter C FILE* handle; und ähnliches wird es unter PHP leider nicht geben :wink:

Da bietet sich die Batch-Konvertierung von IrfanView an :p :smiley:

irfanview.de/

Oder Skriptoptimierung :wink:
Und wenn das auch nicht hilft ein Server mit exec()

ok, ich sehe schon, da muss ich wohl nochmals über die Bücher… o.0

Vielen Dank euch allen für eure Hilfe