Optimisation de code / Fatal error: Allowed memory size

Petit nouveau ! | 7 Messages

21 mars 2009, 19:05

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.

Eléphant du PHP | 141 Messages

21 mars 2009, 19:21

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.

Petit nouveau ! | 7 Messages

24 mars 2009, 10:53

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';
		}
	}
?>

Eléphant du PHP | 141 Messages

24 mars 2009, 11:01

Comment ça le navigateur plante ?

Petit nouveau ! | 7 Messages

24 mars 2009, 11:15

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...

Eléphant du PHP | 141 Messages

24 mars 2009, 11:53

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).