2009-07-13 7 views
5

Czy jest jakiś sposób, aby zabrakło pamięci w PHP GD image library? W przypadku przesłania zbyt dużego obrazu, GD ma tendencję do wyczerpania pamięci, kończąc skrypt. Chciałbym, żeby rzucił wyjątek chwytający lub coś podobnego, ale niestety.Niezawodny sposób, aby zapobiec wyczerpaniu pamięci w bibliotece obrazów GD? (PHP)

W tej chwili używam skleconego razem skryptu, który po raz pierwszy wydaje ini_set('memory_limit', '128M'), jeśli to działa, jestem zwykle ustawiony. W zależności od konfiguracji serwera, choć może nie być to możliwe, powracam do algorytmu, który próbuje oszacować ilość potrzebnej pamięci (biorąc pod uwagę rozdzielczość, głębię kolorów, kanały i współczynnik krówki), a następnie porównuje ją z memory_get_usage(), jeśli funkcja istnieje, w przeciwnym razie zgrubne oszacowanie.

Cała sprawa działa do tej pory, ale na pewno nie jest elegancka i kończy się niepowodzeniem w niektórych przypadkach. Czy istnieje lepszy sposób, aby to zrobić, tj. Czy GD zawodzi z wdziękiem, jeśli musi, zamiast zmielenia wszystkiego do zatrzymania?

+1

Duże obrazy JPEG (nie-PNG lub inne typy) może być zmieniany podczas załadunku, zobacz tę odpowiedź dla dalszych szczegółów: http://stackoverflow.com/questions/12661/efficient-jpeg-image-resizing- in-php/4613341 # 4613341 –

Odpowiedz

3

Kup więcej pamięci! :-P

Poważnie, nie można poradzić sobie z brakującą pamięcią, ponieważ wszelkie podejmowane działania wymagałyby więcej pamięci.

Najlepiej jest ograniczyć rozmiar przesyłanego obrazu na podstawie bieżących ustawień pamięci.

+2

LOL, kup mi hosta z większą ilością pamięci. ;-) Cóż, przynajmniej chciałbym, aby GD oszacowało własne wykorzystanie pamięci, zamiast mnie, aby uniknąć zgadywania błędów i wstrzymać oddech. Nie mogę po prostu ograniczyć obrazu według rozmiaru pliku. Mały plik z bardzo skompresowanym JPG o wysokiej rozdzielczości może pochłonąć więcej pamięci niż duży plik z PNG o niskiej rozdzielczości. Właśnie dlatego muszę wycofać się z wyżej wymienionych obliczeń. – deceze

0

Najlepiej jest przestać próbować dowiedzieć się, ile pamięci RAM będzie potrzebować, i po prostu zwiększyć ją na samym początku - jeśli masz 4 GB, powiedz skryptowi graficznemu, aby używał od 2 do 4 GB danych , a kiedy skrypt się kończy, powinien wrócić do normalności, aby objąć wszystkie potencjalnie śmiertelne sytuacje. To jedyny "bezpieczny" sposób, o którym i tak myślę ...

+0

To właśnie próbuję zrobić, ale rzadko jest to możliwe na współdzielonych hostach. W takich przypadkach robię najlepsze wyliczenia, aby uniknąć zerwania. – deceze

+0

Ustawienie limitu pamięci PHP równego całkowitej ilości pamięci RAM, którą system ma lub gdziekolwiek w pobliżu, pozwoli użytkownikom na wywołanie systemu DOS za pomocą skryptu obrazu. Określenie, ile pamięci RAM jest potrzebne wcześniej, to jedyny sposób, jaki mogę wymyślić, aby zapobiec tego typu DOS-owi. –

1

Jest inny sposób, aby to zrobić, ale może to być czasochłonne, ponieważ niektóre części procesu edycji obrazu powtarza się kilka razy. razy, ale możesz ustawić limit pamięci na wartość szacunkową, a następnie spróbuj przetworzyć obraz, jeśli nie uda się złapać wyjątku, zwiększ limit pamięci, a następnie ponownie przetworzyć obraz - powtarzając to do momentu osiągnięcia sukcesu lub osiągnięcia określonego limitu pamięci - w którym momencie wyświetliłby się komunikat o błędzie dla użytkownika wyjaśniający, że jego obraz jest zbyt duży, aby go użyć.

Edit: Aby złapać błąd out-of-pamięci, można użyć tego rozwiązania: http://au2.php.net/set_error_handler#35622

+0

Jeszcze raz, AFAIK, nie ma nic łatwego do rzucenia. Jest to jednorazowa operacja "pracuj lub nie". O ile nie możesz mi powiedzieć, jak złapać błąd braku pamięci, o to pytam. :) – deceze

+2

Istnieje sposób na złapanie tych błędów: http://au2.php.net/set_error_handler#35622 – jsnfwlr

+0

Będę musiał sprawdzić, czy to rzeczywiście pomaga, jak zauważył Nick, będę musiał użyć więcej pamięci aby poradzić sobie z błędem po jego wystąpieniu. – deceze

0

złapać fatalne błędy PHP, jak "Out of memory" lub „PHP Fatal error: Dozwolony rozmiar pamięci 8388608 bajty wyczerpane (próbowano przydzielić ... bajtów) w ", zobacz tutaj: http://php.net/manual/en/function.set-error-handler.php#88401

+0

Gdy w skrypcie PHP brakuje pamięci, nie można wywołać funkcji wyłączania, ponieważ wymagałoby to przydzielenia większej ilości pamięci. – scotts

3

Po utworzeniu obrazu.

imagepng($image); 
imagedestroy($image); 

usunie problemu pamięci

+0

To powinno być oznaczone jako odpowiedź, zadziałało jak urok dla mnie. – Vic

+0

To powinno ** nie ** być oznaczone jako odpowiedź. Niszczenie obrazu oszczędza zużycie pamięci, ale w żaden sposób nie sprawia, że ​​GD zachowuje się bardziej wdzięcznie. – Glutexo

0

Czy jakieś badania, aby sprawdzić, ile pamięci każdą potrzebę gd funkcyjny.

  • imagecreatetruecolor wydaje się potrzeba width*height*5 bytes.

  • imagepng wydaje się potrzebować width*height*4 bytes.

+0

Dlaczego 'imagecreatetruecolor' potrzebuje 5 bajtów na piksel? Brzmi jak nieparzysta liczba. – Luke

+0

ponieważ obsługa alpha została dodana długo po imagecreate, a wiele funkcji prawdopodobnie miało założenia niż 4 bajt był zawsze 0, więc nie można go użyć ... lub pomyśleli/zobaczyli, że jest zbyt skomplikowany, aby go użyć i stworzyłem nowy. – sebbu

+0

Czy masz jakieś doświadczenie również przy ładowaniu istniejących obrazów na wierzchu? na przykład dla jpg lub png? Używam x * y * ~ 5 dla jpg, ~ 8 dla png, na górze bieżącego użycia mem. jeśli przekracza to limit pamięci, ustawię wyjątek. Ale: Ustawienie 64M jako limitu i posiadanie 2 MB przesłanego jpg może czasem przerwać operację. Jpg wydaje się używać czasem więcej pamięci. Kompresja? Jakieś inne dane exif? gdzie mogę poprawić obliczenia? – flobee

Powiązane problemy