Page 1 sur 1

Optimisation de code / Fatal error: Allowed memory size

Posté : 21 mars 2009, 19:05
par Rockntrek
Bonjour.

Voilà, je me bat avec un code PHP que j'ai écris avec l'aide de plusieurs exemple sur le net, qui permet de réceptionner 1 ou plusieurs images d'un fichier flash pour ensuite les fusionner en une seule.

Mes connaissances en PHP ne vont pas très loin et lors de l'exécution du script, pour une image de grande taille découpé en 4 parties, j'ai l'erreur suivante :

Code : Tout sélectionner

Fatal error: Allowed memory size of 36700160 bytes exhausted (tried to allocate 1896 bytes) in ...
Il y a beaucoup de chose qui se répète mais je ne vois pas trop comment éviter ces répétition justement...

Voilà le code PHP :
<?php
	$path = $_POST[ 'path' ]; // Url absolue
	$put = $_POST[ 'put' ]; // chemin relatif
	
	$width = $_POST[ 'width' ]; // Largeur finale de l'image
	$height = $_POST[ 'height' ]; // Hauteur finale de l'image
	
	$hnd = date("HmsdmY");
	$pif = rand(0, 999);
	$code = $hnd . $pif;
	
	$nameFile = $put . $code .'.jpg';
	
	if($_POST['file2'] != null)
	{
		$nameFile2 = $put . $code .'2.jpg';
		
		if($_POST['file3'] != null)
		{
			$nameFile3 = $put . $code . '3.jpg';
			
			if($_POST['file4'] != null)
			{
				$nameFile4 = $put . $code . '4.jpg';
				
				if(file_put_contents($nameFile, base64_decode($_POST['file'])))
				{
					if(file_put_contents($nameFile2, base64_decode($_POST['file2'])))
					{
						if(file_put_contents($nameFile3, base64_decode($_POST['file3'])))
						{
							if(file_put_contents($nameFile4, base64_decode($_POST['file4'])))
							{
								if($dstFile = imagecreatetruecolor ($width, $height))
								{
									$dstWidth = imagesx($dstFile);
									$dstHeight = imagesy($dstFile);	
								}
								else
								{
									echo 'ERROR';
									unlink($nameFile);
									unlink($nameFile2);
									unlink($nameFile3);
									unlink($nameFile4);
								}
								if($srcFile = imagecreatefromjpeg($nameFile))
								{
									$srcWidth = imagesx($srcFile);
									$srcHeight = imagesy($srcFile);				
								}
								else
								{
									echo 'ERROR';
									unlink($nameFile);
									unlink($nameFile2);
									unlink($nameFile3);
									unlink($nameFile4);
								}
								if($srcFile2 = imagecreatefromjpeg($nameFile2))
								{
									$srcWidth2 = imagesx($srcFile2);
									$srcHeight2 = imagesy($srcFile2);
								}
								else
								{
									echo 'ERROR';
									unlink($nameFile);
									unlink($nameFile2);
									unlink($nameFile3);
									unlink($nameFile4);
								}
								if($srcFile3 = imagecreatefromjpeg($nameFile3))
								{
									$srcWidth3 = imagesx($srcFile3);
									$srcHeight3 = imagesy($srcFile3);
								}
								else
								{
									echo 'ERROR';
									unlink($nameFile);
									unlink($nameFile2);
									unlink($nameFile3);
									unlink($nameFile4);
								}
								if($srcFile4 = imagecreatefromjpeg($nameFile4))
								{
									$srcWidth4 = imagesx($srcFile4);
									$srcHeight4 = imagesy($srcFile4);
								}
								else
								{
									echo 'ERROR';
									unlink($nameFile);
									unlink($nameFile2);
									unlink($nameFile3);
									unlink($nameFile4);
								}
								$posX = 0;
								$posX2 = $dstWidth / 4;
								$posX3 = ($dstWidth / 4) * 2;
								$posX4 = ($dstWidth / 4) * 3;
								$posY = 0;
								if(imagecopymerge($dstFile, $srcFile, $posX, $posY, 0, 0, $srcWidth, $srcHeight, 100))
								{
									if(imagecopymerge($dstFile, $srcFile2, $posX2, $posY, 0, 0, $srcWidth2, $srcHeight2, 100))
									{
										if(imagecopymerge($dstFile, $srcFile3, $posX3, $posY, 0, 0, $srcWidth3, $srcHeight3, 100))
										{
											if(imagecopymerge($dstFile, $srcFile4, $posX4, $posY, 0, 0, $srcWidth4, $srcHeight4, 100))
											{
												header("Content-type: image/jpeg");
												
												if(imagejpeg($dstFile, $nameFile))
												{
													echo 'OK';
													unlink($nameFile2);
													unlink($nameFile3);
													unlink($nameFile4);
												}
												else
												{
													echo 'ERROR';
													unlink($nameFile);
													unlink($nameFile2);
													unlink($nameFile3);
													unlink($nameFile4);
												} 
											}
											else
											{
												echo 'ERROR';
												unlink($nameFile);
												unlink($nameFile2);
												unlink($nameFile3);
												unlink($nameFile4);
											}
										}
										else
										{
											echo 'ERROR';
											unlink($nameFile);
											unlink($nameFile2);
											unlink($nameFile3);
											unlink($nameFile4);
										}
									}
									else
									{
										echo 'ERROR';
										unlink($nameFile);
										unlink($nameFile2);
										unlink($nameFile3);
										unlink($nameFile4);
									}
								}
								else
								{
									echo 'ERROR';
									unlink($nameFile);
									unlink($nameFile2);
									unlink($nameFile3);
									unlink($nameFile4);
								}
								imagedestroy($dstFile);
								imagedestroy($srcFile);
								imagedestroy($srcFile2);
								imagedestroy($srcFile4);
							}
							else
							{
								echo 'ERROR';
								unlink($nameFile);
								unlink($nameFile2);
								unlink($nameFile3);
							}
						}
						else
						{
							echo 'ERROR';
							unlink($nameFile);
							unlink($nameFile2);
						}
					}
					else
					{
						echo 'ERROR';
						unlink($nameFile);
					}
				}
				else
				{
					echo 'ERROR';
				}
			}
			else
			{
				if(file_put_contents($nameFile, base64_decode($_POST['file'])))
				{
					if(file_put_contents($nameFile2, base64_decode($_POST['file2'])))
					{
						if(file_put_contents($nameFile3, base64_decode($_POST['file3'])))
						{
							if($dstFile = imagecreatetruecolor ($width, $height))
							{
								$dstWidth = imagesx($dstFile);
								$dstHeight = imagesy($dstFile);	
							}
							else
							{
								echo 'ERROR';
								unlink($nameFile);
								unlink($nameFile2);
								unlink($nameFile3);
							}
							if($srcFile = imagecreatefromjpeg($nameFile))
							{
								$srcWidth = imagesx($srcFile);
								$srcHeight = imagesy($srcFile);				
							}
							else
							{
								echo 'ERROR';
								unlink($nameFile);
								unlink($nameFile2);
								unlink($nameFile3);
							}
							if($srcFile2 = imagecreatefromjpeg($nameFile2))
							{
								$srcWidth2 = imagesx($srcFile2);
								$srcHeight2 = imagesy($srcFile2);
							}
							else
							{
								echo 'ERROR';
								unlink($nameFile);
								unlink($nameFile2);
								unlink($nameFile3);
							}
							if($srcFile3 = imagecreatefromjpeg($nameFile3))
							{
								$srcWidth3 = imagesx($srcFile3);
								$srcHeight3 = imagesy($srcFile3);
							}
							else
							{
								echo 'ERROR';
								unlink($nameFile);
								unlink($nameFile2);
								unlink($nameFile3);
							}
							$posX = 0;
							$posX2 = $dstWidth / 3;
							$posX3 = ($dstWidth / 3) * 2;
							$posY = 0;
							if(imagecopymerge($dstFile, $srcFile, $posX, $posY, 0, 0, $srcWidth, $srcHeight, 100))
							{
								if(imagecopymerge($dstFile, $srcFile2, $posX2, $posY, 0, 0, $srcWidth2, $srcHeight2, 100))
								{
									if(imagecopymerge($dstFile, $srcFile3, $posX3, $posY, 0, 0, $srcWidth3, $srcHeight3, 100))
									{
										header("Content-type: image/jpeg");
									
										if(imagejpeg($dstFile, $nameFile))
										{
											echo 'OK';
											unlink($nameFile2);
											unlink($nameFile3);
										}
										else
										{
											echo 'ERROR';
											unlink($nameFile);
											unlink($nameFile2);
											unlink($nameFile3);
										} 
									}
									else
									{
										echo 'ERROR';
										unlink($nameFile);
										unlink($nameFile2);
										unlink($nameFile3);
									}
								}
								else
								{
									echo 'ERROR';
									unlink($nameFile);
									unlink($nameFile2);
									unlink($nameFile3);
								}
							}
							else
							{
								echo 'ERROR';
								unlink($nameFile);
								unlink($nameFile2);
								unlink($nameFile3);
							}
							imagedestroy($dstFile);
							imagedestroy($srcFile);
							imagedestroy($srcFile2);
							imagedestroy($srcFile3);
						}
						else
						{
							echo 'ERROR';
							unlink($nameFile);
							unlink($nameFile2);
						}
					}
					else
					{
						echo 'ERROR';
						unlink($nameFile);
					}
				}
				else
				{
					echo 'ERROR';
				}
			}
		}
		else
		{
			if(file_put_contents($nameFile, base64_decode($_POST['file'])))
			{
				if(file_put_contents($nameFile2, base64_decode($_POST['file2'])))
				{
					if($dstFile = imagecreatetruecolor ($width, $height))
					{
						$dstWidth = imagesx($dstFile);
						$dstHeight = imagesy($dstFile);	
					}
					else
					{
						echo 'ERROR';
						unlink($nameFile);
						unlink($nameFile2);
					}
					if($srcFile = imagecreatefromjpeg($nameFile))
					{
						$srcWidth = imagesx($srcFile);
						$srcHeight = imagesy($srcFile);				
					}
					else
					{
						echo 'ERROR';
						unlink($nameFile);
						unlink($nameFile2);
					}
					if($srcFile2 = imagecreatefromjpeg($nameFile2))
					{
						$srcWidth2 = imagesx($srcFile2);
						$srcHeight2 = imagesy($srcFile2);
					}
					else
					{
						echo 'ERROR';
						unlink($nameFile);
						unlink($nameFile2);
					}
					
					$posX = 0;
					$posX2 = $dstWidth / 2;
					$posY = 0;
					
					if(imagecopymerge($dstFile, $srcFile, $posX, $posY, 0, 0, $srcWidth, $srcHeight, 100))
					{
						if(imagecopymerge($dstFile, $srcFile2, $posX2, $posY, 0, 0, $srcWidth2, $srcHeight2, 100))
						{
							if(imagejpeg($dstFile, $nameFile))
							{
								echo 'OK';
								unlink($nameFile2);
							}
							else
							{
								echo 'ERROR';
								unlink($nameFile);
								unlink($nameFile2);
							} 
						}
						else
						{
							echo 'ERROR';
							unlink($nameFile);
							unlink($nameFile2);
						}
					}
					else
					{
						echo 'ERROR';
						unlink($nameFile);
						unlink($nameFile2);
					}
					imagedestroy($dstFile);
					imagedestroy($srcFile);
					imagedestroy($srcFile2);
				}
				else
				{
					echo 'ERROR';
					unlink($nameFile);
				}
			}
			else
			{
				echo 'ERROR';
			}
		}
	}
	else
	{
		if(file_put_contents($nameFile, base64_decode($_POST['file'])))
		{
			echo 'OK';
		}
		else
		{
			echo 'ERROR';
		}
	}
?>
Quelqu'un pourrait-il me donner des conseils sur l'optimisation de ce code stp ?

D'avance merci.

Posté : 21 mars 2009, 19:21
par julian
Je pense que tu peux extraire de ce code, une partie de traitement qui se fait image par image.
Donc tu traite une à une ce que tu peux pour chacune de tes 4 images, que tu sauvegarde sur le serveur en tant que fichier (et tu libère la mémoire).
Ensuite, tu reprends tes 4 fichiers modifiés et tu les fusionnent.

Posté : 24 mars 2009, 10:53
par Rockntrek
Merci pour ta réponse Julian.

J'ai donc essayé d'optimiser le code en suivant tes conseils seulement, de la manière ou j'ai modifier ce dernier, le navigateur plante à chaque fois et je ne comprends pas pourquoi alors que la mémoire est libéré à chaque partie d'image...
<?php
	$path = $_POST[ 'path' ];
	$put = $_POST[ 'put' ];
	
	$width = $_POST[ 'width' ];
	$height = $_POST[ 'height' ];
	
	$hnd = date("HmsdmY");
	$pif = rand(0, 999);
	$code = $hnd . $pif;
	
	$nbFiles = 0;
	$idFile = 0;
	
	/* TRAITEMENT D'UNE IMAGE ENTIERE */
	$nameFile = $put . $code .'.jpg';
	if(file_put_contents($nameFile, base64_decode($_POST['file'])))
	{
		echo 'RECEPTION IMAGE ' . $id . ' - ';
		if($_POST['file2'] != null)
		{	
			$nbFiles ++;
			saveImage($nbFiles + 1, $width, $height, $put, $code);
		}
		else
		{
			echo 'OK';
		}
	}
	else
	{
		echo 'ERROR';
	}
	
	/* ENREGISTREMENT EN PLUSIEURS IMAGES */
	function saveImage($id, $w, $h, $url, $no)
	{
		echo 'FONCTION SAVE IMGE - ';
		if($_POST['file' . $id] != null)
		{
			echo 'RECEPTION IMAGE ' . $id . ' - ';
			
			if(file_put_contents($url . $no . $id . '.jpg', base64_decode($_POST[ 'file' . $id ])))
			{
				echo 'OK';
				$nbFiles ++;
				saveImage($nbFiles + 1, $w, $h);
			}
			else
			{
				echo 'ERROR';
			}
		}
		else
		{
			echo 'FIN DE RECEPTION DES IMAGES';
			
			if($dstFile = imagecreatetruecolor($w, $h))
			{
				$dstWidth = imagesx($dstFile);
				
				$idFile = $nbFiles;
				mergeImage($idFile, $dstFile, $dstWidth, $url, $no);
			}
			else
			{
				echo 'ERROR';
			}
		}
	}
	
	/* FUSION DES DIFFERENTES IMAGES */
	function mergeImage($id, $img, $w, $path, $nb)
	{	
		$posY = 0;
		if($id = 1)
		{
			$posX = 0;
			$name = $path . $nb . '.jpg';
		}
		else
		{
			$posX = ($w / ($nbFiles)) * ($id - 1);
			$name = $path . $nb . $id . '.jpg';
		}
		
		if($srcFile = imagecreatefromjpeg($name))
		{
			$srcWidth = imagesx($srcFile);
			$srcHeight = imagesy($srcFile);
			
			echo 'FUSION IMAGE ' . $id . ' - ';
			
			if(imagecopymerge($img, $srcFile, $posX, $posY, 0, 0, $srcWidth, $srcHeight, 100))
			{
				imagedestroy($srcFile);
				
				unlink($path . $nb . $id . '.jpg');
				
				if(imagejpeg($img, $path . $nb . '.jpg'))
				{
					if($id != 1)
					{
						$idFile --;
						mergeImage($idFile, $img, $w, $path, $nb);
					}
					else
					{
						echo 'OK';
					}
				}
				else
				{
					echo 'ERROR';
				}
			}
			else
			{
				echo 'ERROR';
			}
		}
		else
		{
			echo 'ERROR';
		}
	}
?>

Posté : 24 mars 2009, 11:01
par julian
Comment ça le navigateur plante ?

Posté : 24 mars 2009, 11:15
par Rockntrek
Bug, plus rien de réponds, je suis obligé de le fermer et de le relancer.
Tandis que si j'utilise le premier script alors ça passe (pour une image de taille normale).

Je me demande s'il ne faut pas que je passe par plusieurs fichiers PHP à inclure au fichier PHP appelé par l'application. Du style, un fichier qui contiendrait la fonction saveImage et un autre la fonction mergeImage...

Posté : 24 mars 2009, 11:53
par julian
Le problème c'est que dans tous les cas, tu va dépendre de la taille des images.
Je te conseillerai (si tu peux) de commencer par redimensionner tes images d'origine à des format raisonnables.

Ensuite, commences par supprimer le merge de tes images et regardes à la main si chacune d'elles est bien traitée.
Après, à partir de tes images traitées, tu ne fais QUE le merge pour voir si tout se passe bien également.

Fais ça sur des petites images d'abord (juste pour voir si ton script fonctionne bien (car il est possible que tu boucle en continue si ton navigateur plante).