PHP
Przetwarzanie obrazu za pomocą GD
Szukaj…
Uwagi
Podczas korzystania z header("Content-Type: $mimeType");
i image____
aby wygenerować tylko obraz na wyjściu, pamiętaj, aby nie wysyłać nic więcej, zanotuj nawet pustą linię po ?>
. (Może to być trudny „błąd” do wyśledzenia - nie otrzymujesz obrazu i nie masz pojęcia, dlaczego). Ogólna rada to w ogóle nie uwzględniać?>.
Tworzenie obrazu
Aby utworzyć pusty obraz, użyj funkcji imagecreatetruecolor
:
$img = imagecreatetruecolor($width, $height);
$img
jest teraz zmienną zasobów dla zasobu obrazu o pikselach o $width
x $height
. Pamiętaj, że szerokość liczy się od lewej do prawej, a wysokość liczy się od góry do dołu.
Zasoby obrazu można również tworzyć za pomocą funkcji tworzenia obrazu , takich jak:
-
imagecreatefrompng
-
imagecreatefromjpeg
- inne
imagecreatefrom*
funkcji.
Zasoby obrazu można zwolnić później, gdy nie będzie już żadnych odniesień do nich. Aby jednak natychmiast zwolnić pamięć (może to być ważne, jeśli przetwarzasz wiele dużych obrazów), imagedestroy()
może być użycie imagedestroy()
na obrazie, gdy nie jest już używany.
imagedestroy($image);
Konwertowanie obrazu
Obrazy utworzone przez konwersję obrazu nie modyfikują obrazu, dopóki go nie wyślesz. Dlatego konwerter obrazów może być tak prosty, jak trzy linie kodu:
function convertJpegToPng(string $filename, string $outputFile) {
$im = imagecreatefromjpeg($filename);
imagepng($im, $outputFile);
imagedestroy($im);
}
Wyjście obrazu
Obraz można utworzyć za pomocą funkcji image*
, gdzie *
to format pliku.
Mają wspólną składnię:
bool image___(resource $im [, mixed $to [ other parameters]] )
Zapisywanie do pliku
Jeśli chcesz zapisać obraz do pliku, możesz przekazać nazwę pliku lub otwarty strumień plików jako $to
. Jeśli przepuścisz strumień, nie musisz go zamykać, ponieważ GD automatycznie go zamknie.
Na przykład, aby zapisać plik PNG:
imagepng($image, "/path/to/target/file.png");
$stream = fopen("phar://path/to/target.phar/file.png", "wb");
imagepng($image2, $stream);
// Don't fclose($stream)
Używając fopen
, upewnij się, że używasz flagi b
zamiast flagi t
, ponieważ plik jest wyjściem binarnym.
Nie staraj się przekazać fopen("php://temp", $f)
lub fopen("php://memory", $f)
do niego. Ponieważ strumień jest zamykany przez funkcję po wywołaniu, nie będzie można go dalej używać, na przykład w celu odzyskania jego zawartości.
Dane wyjściowe jako odpowiedź HTTP
Jeśli chcesz bezpośrednio zwrócić ten obraz jako odpowiedź obrazu (np. W celu utworzenia dynamicznych odznak), nie musisz przekazywać niczego (ani null
) jako drugiego argumentu. Jednak w odpowiedzi HTTP musisz określić typ zawartości:
header("Content-Type: $mimeType");
$mimeType
to typ MIME zwracanego formatu. Przykłady obejmują image/png
, image/gif
i image/jpeg
.
Zapis do zmiennej
Istnieją dwa sposoby zapisywania w zmiennej.
Korzystanie z OB (buforowanie wyjściowe)
ob_start();
imagepng($image, null, $quality); // pass null to supposedly write to stdout
$binary = ob_get_clean();
Korzystanie z opakowań strumieniowych
Możesz mieć wiele powodów, dla których nie chcesz używać buforowania danych wyjściowych. Na przykład możesz już mieć włączony system operacyjny. Dlatego potrzebna jest alternatywa.
Za pomocą funkcji stream_wrapper_register
można zarejestrować nowe opakowanie strumienia. Dlatego możesz przekazać strumień do funkcji wyjściowej obrazu i odzyskać go później.
<?php
class GlobalStream{
private $var;
public function stream_open(string $path){
$this->var =& $GLOBALS[parse_url($path)["host"]];
return true;
}
public function stream_write(string $data){
$this->var .= $data;
return strlen($data);
}
}
stream_wrapper_register("global", GlobalStream::class);
$image = imagecreatetruecolor(100, 100);
imagefill($image, 0, 0, imagecolorallocate($image, 0, 0, 0));
$stream = fopen("global://myImage", "");
imagepng($image, $stream);
echo base64_encode($myImage);
W tym przykładzie klasa GlobalStream
zapisuje wszelkie dane wejściowe do zmiennej referencyjnej (tj. Pośrednio zapisuje zmienną globalną o podanej nazwie). Zmienna globalna może być później pobrana bezpośrednio.
Należy zwrócić uwagę na kilka specjalnych rzeczy:
- W pełni wdrożone strumień klasy otoki powinien wyglądać jak ten , ale według badań z
__call
metody magiczne, tylkostream_open
,stream_write
istream_close
nazywane są od funkcji wewnętrznych. - W wywołaniu
fopen
nie są wymagane flagi, ale należy przynajmniej przekazać pusty ciąg znaków. Wynika to z faktu, że funkcjafopen
oczekuje takiego parametru, a nawet jeśli nie użyjesz go w implementacjistream_open
, to nadal jest on wymagany. - Według testów
stream_write
jest wywoływany wiele razy. Pamiętaj, aby użyć.=
(Przypisanie konkatenacji), a nie=
(bezpośrednie przypisanie zmiennej).
Przykładowe użycie
W tagu HTML <img>
obraz można podać bezpośrednio, zamiast używać zewnętrznego łącza:
echo '<img src="data:image/png;base64,' . base64_encode($binary) . '">';
Kadrowanie i zmiana rozmiaru obrazu
Jeśli masz obraz i chcesz utworzyć nowy obraz z nowymi wymiarami, możesz użyć funkcji imagecopyresampled
:
najpierw utwórz nowy image
o pożądanych wymiarach:
// new image
$dst_img = imagecreatetruecolor($width, $height);
i zapisz oryginalny obraz w zmiennej. Aby to zrobić, możesz użyć jednej z funkcji createimagefrom*
gdzie * oznacza:
- jpeg
- gif
- png
- strunowy
Na przykład:
//original image
$src_img=imagecreatefromstring(file_get_contents($original_image_path));
Teraz skopiuj cały (lub część) oryginalnego obrazu (src_img) do nowego obrazu (dst_img) przez imagecopyresampled
:
imagecopyresampled($dst_img, $src_img,
$dst_x ,$dst_y, $src_x, $src_y,
$dst_width, $dst_height, $src_width, $src_height);
Aby ustawić src_*
i dst_*
, użyj poniższego obrazu:
Teraz, jeśli chcesz skopiować cały obraz źródłowy (początkowy), do całego obszaru docelowego (bez przycinania):
$src_x = $src_y = $dst_x = $dst_y = 0;
$dst_width = $width;// width of new image
$dst_height = $height; //height of new image
$src_width = imagesx($src_img); //width of initial image
$src_height = imagesy($src_img); //height of initial image