Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] Opytmalizacja operacji
Forum PHP.pl > Forum > PHP
smarcz
Witam!

Problem polega na optymalizacji operacji w trakcie przetwarzania obrazka - zmiana rozdzielczosci i jego ponowne zapisanie! Przesyłanych pól w formularzu jest 7. Problem zaczyna się kiedy wysyłam pliki graficzne których wielkości przekracza 256 kb - i jest ich kila w pewnym momencie pojawia się błąd o treści:
Fatal error: Allowed memory size of 20971520 bytes exhausted (tried to allocate 8704 bytes) in /home/.../ftp/.../spr3.php on line 101

Serwer na którym pracuje ma wprowadzone ograniczenie 20MB.

Może znacie sposób obróbki obrazka inny niż ja - lub jak podzielić mój skrypt na operacje aby się zmieścić w limicie??

Oto kod!:

  1. function k1(){
  2. ?>
  3. <FORM name="f1" METHOD="POST" ACTION="<?php echo $PHP_SELF ?>" enctype="multipart/form-data">
  4. <INPUT TYPE="HIDDEN" NAME="action" VALUE="d1">
  5.  
  6. <input type="file" name="zdj_p1" size="20">
  7. <div align="center">
  8. <input type="submit" name="w" value="Zapisz">
  9. <input type="reset" value="Skasuj">
  10. </div>
  11. </FORM>
  12. <?
  13. }
  14. function d1(){
  15.  
  16. $zdj1 = $_FILES['zdj_p1'];
  17.  
  18. $stos=0;
  19.  
  20. if(!empty($zdj1)){
  21. $stos++;
  22.  
  23. //Zapisywanie wartości zdjęcia do zmiennych
  24. $nazwa = $_FILES['zdj_p1']['name'];
  25. $typ  = $_FILES['zdj_p1']['type'];
  26. $size = $_FILES['zdj_p1']['size'];
  27. $plik = $_FILES['zdj_p1']['tmp_name'];
  28.  
  29. $wielkosc = 200000;//Wielkość przesyłanego pliku - 200KB
  30. $x = 600;//Szerokość w Pixelach
  31.  
  32. $filename = '';
  33. $filename .= $stos;
  34. $filename .= date("YmdHis");
  35. $filename .= $id;
  36. $filename .= 'o';
  37.  
  38. $mojaNazwa = $filename.'.jpg';
  39.  
  40. $sciezka = 'img/';
  41. //Przetwarzanie obrazka z formatu jpg i jpeg
  42. if (ereg("image/jpeg", $typ)){
  43. echo "to jest JPG<br>";
  44.  
  45. $zdj = ImageCreateFromJpeg($plik);
  46. $zdjx = ImageSX($zdj);
  47. $zdjy = ImageSY($zdj);
  48.  
  49. $y = ceil($zdjy*($x/$zdjx));
  50. $nowezdj = imagecreatetruecolor($x, $y);
  51. imagecopyresized($nowezdj,$zdj,0,0,0,0,$x,$y,$zdjx,$zdjy);
  52. imagejpeg($nowezdj, $sciezka . $mojaNazwa ,100);
  53. }
  54.  
  55. //Przetwarzanie obrazka z formatu gif
  56. elseif(ereg("image/gif", $typ)){
  57. echo "to jest GIF<br>";
  58.  
  59. $zdj = ImageCreateFromGIF($plik);
  60. $zdjx = ImageSX($zdj);
  61. $zdjy = ImageSY($zdj);
  62.  
  63. $y = ceil($zdjy*($x/$zdjx));
  64. $nowezdj = imagecreatetruecolor($x, $y);
  65. imagecopyresized($nowezdj,$zdj,0,0,0,0,$x,$y,$zdjx,$zdjy);
  66. imagejpeg($nowezdj, $sciezka . $mojaNazwa ,100);
  67. }
  68.  
  69. //Przetwarzanie obrazka z formatu png
  70. elseif(ereg("image/png", $typ)){
  71.  
  72. $zdj = ImageCreateFromPng($plik);
  73. $zdjx = ImageSX($zdj);
  74. $zdjy = ImageSY($zdj);
  75.  
  76. $y = ceil($zdjy*($x/$zdjx));
  77. $nowezdj = imagecreatetruecolor($x, $y);
  78. imagecopyresized($nowezdj,$zdj,0,0,0,0,$x,$y,$zdjx,$zdjy);
  79. imagejpeg($nowezdj, $sciezka . $mojaNazwa ,100);
  80. }
  81. else{
  82. echo "Niepoprawny format pliku<br>";
  83. }
  84. }
  85.  
  86. }
  87. ?>


a to wynik działania tego formularza:

array (
'action' => 'd1',
'w' => 'Zapisz',
)

array (
'zdj_p1' =>
array (
'name' => 'list motywacyjny1.jpg',
'type' => 'image/jpeg',
'tmp_name' => '/tmp/php9Izb0I',
'error' => 0,
'size' => 258787,
),
'zdj_p2' =>
array (
'name' => 'List[Andrzej].GIF',
'type' => 'image/gif',
'tmp_name' => '/tmp/phpjCXT0F',
'error' => 0,
'size' => 183603,
),
'zdj_1' =>
array (
'name' => 'error.jpg',
'type' => 'image/jpeg',
'tmp_name' => '/tmp/phpiTN7n4',
'error' => 0,
'size' => 365525,
),
'zdj_2' =>
array (
'name' => '',
'type' => '',
'tmp_name' => '',
'error' => 4,
'size' => 0,
),
'zdj_3' =>
array (
'name' => '',
'type' => '',
'tmp_name' => '',
'error' => 4,
'size' => 0,
),
'zdj_4' =>
array (
'name' => '',
'type' => '',
'tmp_name' => '',
'error' => 4,
'size' => 0,
),
'zdj_5' =>
array (
'name' => '',
'type' => '',
'tmp_name' => '',
'error' => 4,
'size' => 0,
),
)

Nazwa - list motywacyjny1.jpg
Typ - image/jpeg
Wielko�ć kb - 258787
to jest JPG

Fatal error: Allowed memory size of 20971520 bytes exhausted (tried to allocate 8704 bytes) in /home/.../ftp/.../spr3.php on line 101
yaotzin
  1. <input type="file" name="zdj_p1" size="20">


A tu nie powinno być przypadkiem tak questionmark.gif

  1. <input type="file" name="zdj_p1" size="200000">


size określa wielkośc wrzucanego pliku na serwer, łatwe do obejścia, ale jest częstą przyczyną błędów u początkujących. PZDR
Kicok
sprawdź czy wydajność się poprawi gdy zaczniesz stosować imagedestroy" title="Zobacz w manualu PHP" target="_manual
smarcz
Dzięki za podpowiedź Kicok, też czytałem o tym dziś w Manualu - zastosowałem nic z tego. Tu chodzi chyba o pamięć CACHE serwera. Bo czasem jest tak, że pierwszy (1) plik dodawany w formularzu (7 pól input files) ma pojemność większą niż 200 kb i bład Fatal Error pojawia się dla linii kodu:

  1. <?php
  2. $zdj = ImageCreateFrom?questionmark.gif($plik);
  3. ?>


Że pamięc została przekroczona - tak więc nie wiem od czego to zależy!? sad.gif

Wygląda to tak, jakby plik który idzie do przetwarzania powiększał się. Może jest jakiś sposób na określenie pamięci dla takiej operacji. Czytałem dziś w Manualu na temat: clearstatcache — Czyści bufor statusu pliku lub memory_get_usage

Może jest jakieś polecenie które wyświetla stan pamięci BUFORA. Ja potrzebuje się zmieścić w 20 MB na serwerze. Chyba, że jest jakiś inny sposób na zmianę rozdzielczości obrazka??

----00.33 27.02.2007----

Tak więc po kilkunastu testach z użyciem funkcji memory_get_usage() - która wyświetla pamięć używaną stwierdzam:

Plik jpg który ma wielkość [bajtach] 615184 (601 kb) po wykonaniu poniższego kodu:

  1. <?php
  2. if(!empty($zdj1)){
  3. $stos++;
  4.  
  5. //Zapisywanie wartości zdjęcia do zmiennych
  6. $nazwa = $_FILES['zdj_p1']['name'];
  7. $typ  = $_FILES['zdj_p1']['type'];
  8. $size = $_FILES['zdj_p1']['size'];
  9. $plik = $_FILES['zdj_p1']['tmp_name'];
  10.  
  11. echo "Nazwa - $nazwa<br>";
  12. echo "Typ - $typ<br>";
  13. echo "Wielkość kb - $size<br>";
  14.  
  15. $wielkosc = 200000;//Wielkość przesyłanego pliku - 200KB
  16. $x = 600;//Szerokość w Pixelach
  17.  
  18. //1.) Tworze nazwę pliku składającą się z numeru pliku w stosie
  19. //2.) Z daty i godziny
  20. //3.) Numeru ID przekazywanego w sesji
  21. //4.) Literki "o" - określającej obiekt
  22.  
  23. $filename = '';
  24. $filename .= $stos;
  25. $filename .= date("YmdHis");
  26. $filename .= $id;
  27. $filename .= 'o';
  28.  
  29. $mojaNazwa = $filename.'.jpg';
  30.  
  31. $sciezka = 'img/';
  32.  
  33. //Przetwarzanie obrazka z formatu jpg i jpeg
  34. if (ereg("image/jpeg", $typ)){
  35. echo "to jest JPG<br>";
  36.  
  37. $zdj = ImageCreateFromJpeg($plik);
  38. echo memory_get_usage() . "<strong>- Po ImageCreate<br></strong>"; // wyświetlam zajmowaną pojemność w bajtach
  39. $zdjx = ImageSX($zdj);
  40. $zdjy = ImageSY($zdj);
  41. echo memory_get_usage() . "<strong>- Po $zdjx i y<br></strong>"; // wyświetlam zajmowaną pojemność w bajtach
  42. $y = ceil($zdjy*($x/$zdjx));
  43. $nowezdj = imagecreatetruecolor($x, $y);
  44. imagecopyresized($nowezdj,$zdj,0,0,0,0,$x,$y,$zdjx,$zdjy);
  45. imagejpeg($nowezdj, $sciezka . $mojaNazwa ,100);
  46. echo memory_get_usage() . "<strong>- Przed imagedestroy<br></strong>"; // wyświetlam zajmowaną pojemność w bajtach
  47. imagedestroy($zdj);
  48. }
  49. }
  50. ?>


zmienia swoją pojemność po stronie serwera następująco:
9780648 - Po ImageCreateFromJpeg($plik);
9780792 - Po zmianie rozdzielczości
11141968 11Mb - Przed imagedestroy
1525056 - Po wykonaniu imagedestroy

I tak mnie nie satysfakcjonuje taka wielkość zajmowanej pamięci - prawie 1,5 MB. Stosując [/u]unset($zmienna) zajmowana pamięć się tylko powiększała. Dziwne bo za pomocą tej funkcji usuwa się zmienna z pamięci. Ale może koledzy macie inne doświadczenia - proszę o testy i przykłady jak zrobić aby wyczyścić bufor poniżej 1 MB?
siemakuba
nie wiem czy to coś pomoże, ale wydaje mi się, że nie musisz zapisywać plików z kompresją ustawioną na 100. Przy zmniejszeniu kompresji do 80-90 (przetestuj) nie zauważysz różnicy w jakości pliku, a jego rozmiar spadnie znacząco - co z kolei powinno mieć wpływ na ilość danych w buforze - właśnie w tym miejscu jest tam największa ilość danych.

pozdr.
smarcz
Tak więc po kolejnym dniu prób - stwierdzam - zmiana kompresji -> znikomy efekt (ale zawsze coś) Jeszcze dziś robiłem testy i co dziwnego odkryłem - bawiłem się z dodawaniem plików jpg z aparatu cyfrowego - niektóre pliki o pojemności powyżej 1 MB prawie 2 MB załączały się przez formularz bez problemu mieszcząc się w dozwolonym buforze 20 MB. Owszem w trakcie wczytywania ImageCreateFrom?questionmark.gif($plik); pamięć bufora skacze do ponad 15 MB ale pliki przechodzą bez problemu. Co ciekawe dołączałem pliki o mniejszej rozdzielczości - np.: 300 Kb - także jpg - i takie pliki w trakcie obróbki ImageCreateFrom?questionmark.gif($plik); przekraczały znacząco zajętość bufora 20 MB. Dlaczego?

Moje pytanie - jak określić przed wczytaniem do ImageCreateFrom?questionmark.gif($plik); ile plik może potrzebować pamięci na taką operację? Szukałem w manualu opisu ile ta bibloteka GD potrzebuje pamięci do przetworzenia 1 pixela obrazka i nie znalazłem. Może macie jakieś doświadczenia z takim zagadnieniem?

Lub inaczej jak stworzyć dla takiego formularza obsługę błędów aby nie pojawiał się komunikat Fatal error i przerywał działanie skryptu - tylko ładnie wcześniej użytkownika poinformować że dodawany plik nie spełnia wymagań?

Może to tędy droga - aby wcześniej wywalić błąd a nie przerywać działania skryptu co jest nieporządane w trakcie zapisu wyników do bazy danych MySQL

Z góry dzięki za wszelkie podpowiedzi. Jakieś gotowe skrypty - możecie pisać na maila smarcz@interia.pl
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.