Seite 1 von 1

Benötigen Arbeitsspeicher berechnen beim Umgang mit Bildern

Verfasst: 07.07.2007 18:59
von mgutt
Hallo,

es gibt zwar hier und da Codeschnippsel, doch keiner davon funktioniert wirklich bei jedem.

Ich habe z.B. herausgefunden, dass grauskalierte JPEGs eine Bittiefe von 8 haben, aber von GD mit 24 Bit abgearbeitet werden. Jedenfalls muss das so sein, da der benötigte Arbeitsspeicher sich im Bereich von 24 Bit abspielt. Daher habe ich eine Funktion geschrieben die möglichst genau den benötigten Speicher ermittelt.

Die Funktion prüft den aktuell genutzten Speicher (falls möglich) und addiert dazu den benötigten Speicher für das Erstellen eines Thumbnails. Sollte die Summe größer sein als der verfügbare Speicher, so wird versucht das Limit neu zu setzen. Funktioniert das nicht, dann resultiert die Funktion ein false.

Das ist auch der einzige Fall, wo ein Fehler resultiert.

Das wäre die Funktion, die man vor dem Erstellen eines Vorschaubildes (Thumbnail) aufrufen sollte:

Code: Alles auswählen

function enough_memory($src_file)
{
	$getimagesize = @getimagesize($src_file);
	if ( $getimagesize && isset($getimagesize[0]) && isset($getimagesize[1]) && isset($getimagesize[2]) && isset($getimagesize['bits']) && isset($getimagesize['channels']) )
	{
		$memory_needed = ($getimagesize[0] * $getimagesize[1] * ($getimagesize[2] == IMG_JPG ? 24 : $getimagesize['bits']) * $getimagesize['channels'] / 8 + pow(2, 16)) * 1.7;
		$memory_limit = intval(ini_get('memory_limit')) * pow(1024, 2); // if --disable-memorylimit is set this is 0
		$memory_usage = 0;
		if ( function_exists('memory_get_usage') )
		{
			$memory_usage = memory_get_usage();
		}
		if ( $memory_limit && ($memory_needed + $memory_usage) > $memory_limit )
		{
			// try to set a new limit
			if ( !ini_set('memory_limit', ceil(($memory_needed + $memory_usage) / pow(1024, 2)) . 'M') )
			{
				return false;
			}
		}
		return true;
	}
	return false;
}
z.B. so:

Code: Alles auswählen

if ( enough_memory('images/bild.jpg')
{
	// thumbnail erstellen
}
EDIT:
Ich habe soeben ein Bild von 40.000 Bildern insgesamt gehabt, dass den Arbeitsspeicher dennoch gesprengt hat. Daher habe ich den Faktor jetzt einfach von 1.65 auf 1.7 (siehe Code) geändert und damit wurde auch das Bild erfolgreich verkleinert.

Gruß

Nachfrage

Verfasst: 03.08.2007 14:20
von sanduleak
Hi, genau so etwas suche ich auch.
Ich verstehe nur die Rechnung nicht ganz.
breite*höhe*farbtiefe müsste doch ausreichen um den Speicherbedarf eines images zu berechnen.
Warum multiplizierst du getimagesize['channels'] und pow(2,16) dazu und wählst den wert *1.7?
Dann verstehe ich nicht warum bei jpeg die Farbtiefe des Bildes keine rolle spielen soll sondern ein andere Farbtiefe?
Wäre schön wenn du zu der Funktion etwas schreiben könntest.
Danke

Verfasst: 03.08.2007 14:34
von PhilippK
Schau mal unter http://de2.php.net/manual/en/function.i ... ecolor.php - da haben sich schon ein paar den Kopf drüber zerbrochen.

Gruß, Philipp

Verfasst: 04.08.2007 00:02
von mgutt
Falscher Link ;)

Hier wurde darüber diskutiert:
http://de2.php.net/imagecreatefromjpeg

Ausgehend war dieser Beitrag:

Code: Alles auswählen

First I supposed simple width*height*bpp will be enough, it isn't though; there is some pretty big overhead.

$imageInfo = GetImageSize($imageFilename);
$memoryNeeded = Round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.65);
Den Rest habe ich aus meinem Massentest ableiten können.

Eigentlich hast Du Recht, wenn Du sagst, dass sich durch breite*höhe*farbtiefe der Speicher ergibt. Aber die GD Library braucht weit aus mehr Speicher, wenn sie mit Bildern arbeitet.

Bei JPGs gibt es eine Sonderregel, die ich bei dem Massentest herausgefunden habe. Das betraf JPGs mit 8 Bit. Die wurden mit dem gleichen Arbeitsspeicher abgearbeitet wie 24 Bit Bilder. Daher setze ich den Wert standardmäßig auf 24 Bit. 32 Bit gab entweder keine Probleme oder die waren einfach nicht dabei.

Weitere Erklärung:
- Breite * Höhe * Farbtiefe = Summe in Bits pro Farbkanal
- Summe pro Farbkanal * Anzahl Farbkanäle = Summe in Bits (Farbkanäle: RGB = 3 und CMYK = 4)
- Summe in Bits / 8 = Summe in Bytes
- Summe in Bytes + 65.536 Bytes für den Buffer = Summe Bild & GD
- Summe Bild & GD * Faktor X = die zu erwartende Nutzung des Arbeitsspeichers beim Abarbeiten des Bildes durch die GD Library

Nachtrag

Verfasst: 05.08.2007 22:29
von sanduleak
Ah vielen Dank, ich habe mich schon gewundert was createTrueColor mit dem Thema zu tun haben sollte.
Wie kann man denn das festellen was im Arbeitsspeicher belegt ist?
Was ich auch noch nicht ganz verstehe ist 65.536 Bytes für den Buffer?
Macht gd nicht eine Kopie vom Bild die dazuzuaddieren ist, also die komprimierte größe des Bildes?
Wenn für jeden Farbkanal 24 bit gilt, dann wären das ja bei bmp z.b. 72 bit, das ist aber komisch. Ich dachte immer 24 insgesamt für das ganze Bild, hm.