Я пытаюсь изменить размер png с прозрачным фоном в PHP, и образцы кода, которые я нашел в Интернете, у меня не работают. Вот код, который я использую, я буду благодарен за совет!
$this->image = imagecreatefrompng($filename);
imagesavealpha($this->image, true);
$newImage = imagecreatetruecolor($width, $height);
// Make a new transparent image and turn off alpha blending to keep the alpha channel
$background = imagecolorallocatealpha($newImage, 255, 255, 255, 127);
imagecolortransparent($newImage, $background);
imagealphablending($newImage, false);
imagesavealpha($newImage, true);
imagecopyresampled($newImage, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
$this->image = $newImage;
imagepng($this->image,$filename);
Обновлять
Под «не работает» я имел в виду, что цвет фона меняется на черный, когда я изменяю размер png.






Насколько я могу судить, вам нужно установить режим наложения на false, а флаг сохранения альфа-канала - на trueдо, вы выполняете imagecolorallocatealpha ()
<?php
/**
* https://stackoverflow.com/a/279310/470749
*
* @param resource $image
* @param int $newWidth
* @param int $newHeight
* @return resource
*/
public function getImageResized($image, int $newWidth, int $newHeight) {
$newImg = imagecreatetruecolor($newWidth, $newHeight);
imagealphablending($newImg, false);
imagesavealpha($newImg, true);
$transparent = imagecolorallocatealpha($newImg, 255, 255, 255, 127);
imagefilledrectangle($newImg, 0, 0, $newWidth, $newHeight, $transparent);
$src_w = imagesx($image);
$src_h = imagesy($image);
imagecopyresampled($newImg, $image, 0, 0, 0, 0, $newWidth, $newHeight, $src_w, $src_h);
return $newImg;
}
?>
ОБНОВИТЬ: этот код работает только с прозрачным фоном с непрозрачностью = 0. Если у вашего изображения 0 <непрозрачность <100, это будет черный фон.
Ответ был совершенно не связан, но это правильный способ изменить размер с помощью прозрачности.
Это определенно ПРАВИЛЬНЫЙ способ создавать / копировать прозрачные изображения PNG.
@RyanDoherty, если это не было ответ, то можете ли вы предоставить свое решение?
у меня это тоже не работает ... фон остается черным. когда я делаю imagecopyresampled, он снова становится черным, даже если он был прозрачным с помощью предыдущих команд ...
Миллион различных методов был испробован из миллиона различных ответов и предложений, и это единственный, который сработал. Спасибо @Dycey
Помните, что ресурс сохраняет прозрачность. Поэтому, если вы скопируете прозрачное изображение на изображение, которое вы только что изменили, оно будет неправильным. Я не смог найти ничего о невыделении прозрачности, поэтому я использовал imagecopy для ресурса с измененным размером, чтобы очистить его. Просто говорю.
Также требуется заливка нового изображения прозрачным цветом (как закодировал Дайси, но я предполагаю, что забыл упомянуть :)), а не только «стратегическая» экономия сама по себе.
IIRC, вам также необходимо убедиться, что PNG 24-битный, то есть истинный цвет, а не 8-битный, чтобы избежать ошибок.
старый поток, но на всякий случай - пример Дайси должен работать, если правильно называть вещи. Вот модифицированная версия, используемая в моем классе изменения размера изображения. Обратите внимание на проверку, чтобы убедиться, что imagecolorallocatealpha () определен, чего не будет, если вы используете GD <2.0.8.
/**
* usually when people use PNGs, it's because they need alpha channel
* support (that means transparency kids). So here we jump through some
* hoops to create a big transparent rectangle which the resampled image
* will be copied on top of. This will prevent GD from using its default
* background, which is black, and almost never correct. Why GD doesn't do
* this automatically, is a good question.
*
* @param $w int width of target image
* @param $h int height of target image
* @return void
* @private
*/
function _preallocate_transparency($w, $h) {
if (!empty($this->filetype) && !empty($this->new_img) && $this->filetype == 'image/png')) {
if (function_exists('imagecolorallocatealpha')) {
imagealphablending($this->new_img, false);
imagesavealpha($this->new_img, true);
$transparent = imagecolorallocatealpha($this->new_img, 255, 255, 255, 127);
imagefilledrectangle($this->new_img, 0, 0, $tw, $th, $transparent);
}
}
}
tw - Ширина цели th - Высота цели
Я думаю, что он имел в виду: tw и th не определены. Параметры функции называются $ w и $ h, но imagefilledrectangle () вызывается с $ tw и $ th. Это ошибка.
у меня это тоже не работает :( это мое решение .. но я также получаю черный фон и изображение не прозрачное
<?php
$img_id = 153;
$source = "images/".$img_id.".png";
$source = imagecreatefrompng($source);
$o_w = imagesx($source);
$o_h = imagesy($source);
$w = 200;
$h = 200;
$newImg = imagecreatetruecolor($w, $h);
imagealphablending($newImg, false);
imagesavealpha($newImg,true);
$transparent = imagecolorallocatealpha($newImg, 255, 255, 255, 127);
imagefilledrectangle($newImg, 0, 0, $w, $h, $transparent);
imagecopyresampled($newImg, $source, 0, 0, 0, 0, $w, $h, $o_w, $o_h);
imagepng($newImg, $img_id.".png");
?>
<img src = "<?php echo $img_id.".png" ?>" />
Полный пример. Обратите внимание, что для некоторых изображений png, найденных в Интернете, он работает некорректно, но для моих собственных, созданных с помощью Photoshop, он работает нормально.
header('Content-Type: image/png');
$filename = "url to some image";
$newWidth = 300;
$newHeight = 300;
$imageInfo = getimagesize($filename);
$image = imagecreatefrompng($filename); //create source image resource
imagesavealpha($image, true); //saving transparency
$newImg = imagecreatetruecolor($newWidth, $newHeight); //creating conteiner for new image
imagealphablending($newImg, false);
imagesavealpha($newImg,true);
$transparent = imagecolorallocatealpha($newImg, 255, 255, 255, 127); //seting transparent background
imagefilledrectangle($newImg, 0, 0, $newWidth, $newHeight, $transparent);
imagecopyresampled($newImg, $image, 0, 0, 0, 0, $newWidth, $newHeight, $imageInfo[0], $imageInfo[1]);
imagepng($newImg); //printout image string
Вот окончательное решение, которое мне подходит.
function resizePng($im, $dst_width, $dst_height) {
$width = imagesx($im);
$height = imagesy($im);
$newImg = imagecreatetruecolor($dst_width, $dst_height);
imagealphablending($newImg, false);
imagesavealpha($newImg, true);
$transparent = imagecolorallocatealpha($newImg, 255, 255, 255, 127);
imagefilledrectangle($newImg, 0, 0, $width, $height, $transparent);
imagecopyresampled($newImg, $im, 0, 0, 0, 0, $dst_width, $dst_height, $width, $height);
return $newImg;
}
Вероятно, это связано с более новыми версиями PHP (я тестировал с PHP 5.6), но теперь это работает без необходимости заливки изображения прозрачным фоном:
$image_p = imagecreatetruecolor(480, 270);
imageAlphaBlending($image_p, false);
imageSaveAlpha($image_p, true);
$image = imagecreatefrompng('image_with_some_transaprency.png');
imagecopyresampled($image_p, $image, 0, 0, 0, 0, 480, 270, 1920, 1080);
imagepng($image_p, 'resized.png', 0);
Да, это работает! imageAlphaBlending и imageSaveAlpha хватит, спасибо;)
Вот полный код, работающий с файлами png с сохранением прозрачности их изображений.
list($width, $height) = getimagesize($filepath);
$new_width = "300";
$new_height = "100";
if ($width>$new_width && $height>$new_height)
{
$image_p = imagecreatetruecolor($new_width, $new_height);
imagealphablending($image_p, false);
imagesavealpha($image_p, true);
$image = imagecreatefrompng($filepath);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
imagepng($image_p,$filepath,5);
}
Ни одно из приведенных выше решений не помогло мне. Вот как я выяснил, как решить проблему.
// upload directory
$upload_dir = "../uploads/";
// valid image formats
$valid_formats = array("jpg", "jpeg", "png");
// maximum image size 1 mb
$max_size = 1048576;
// crop image width, height
$nw = $nh = 800;
$nw1 = $nh1 = 400;
$nw3 = $nh3 = 200;
$nw2 = $nh2 = 100;
// checks that if upload_dir a directory/not
if (is_dir($upload_dir) && is_writeable($upload_dir)) {
// not empty file
if (!empty($_FILES['image'])) {
// assign file name
$name = $_FILES['image']['name'];
// $_FILES to execute all files within a loop
if ($_FILES['image']['error'] == 4) {
$message = "Empty FIle";
}
if ($_FILES['image']['error'] == 0) {
if ($_FILES['image']['size'] > $max_size) {
echo "E-Image is too large!<br>";
$_SESSION['alert'] = "Image is too large!!";
} else if (!in_array(pathinfo($name, PATHINFO_EXTENSION), $valid_formats)) {
$_SESSION['alert'] = "This image is not a valid image format!!";
echo "E-This image is not a valid image format<br>";
} else if (file_exists($upload_dir . $name)) {
$_SESSION['alert'] = "Image already exists!!";
echo "E-Image already exists<br>";
} else { // No error found! Move uploaded files
$size = getimagesize($_FILES['image']['tmp_name']);
$x = (int) $_POST['x'];
$y = (int) $_POST['y'];
$w = (int) $_POST['w'] ? $_POST['w'] : $size[0];
$h = (int) $_POST['h'] ? $_POST['h'] : $size[1];
// path for big image
$big_image_path = $upload_dir . "big/" . $name;
// medium image path
$medium_image_path = $upload_dir . "medium/" . $name;
// small image path
$small_image_path = $upload_dir . "small/" . $name;
// check permission
if (!is_dir($upload_dir . "big/") && !is_writeable($upload_dir . "big/")) {
mkdir($upload_dir . "big/", 0777, false);
}
if (!is_dir($upload_dir . "medium/") && !is_writeable($upload_dir . "medium/")) {
mkdir($upload_dir . "medium/", 0777, false);
}
if (!is_dir($upload_dir . "small/") && !is_writeable($upload_dir . "small/")) {
mkdir($upload_dir . "small/", 0777, false);
}
// image raw data from form
$data = file_get_contents($_FILES["image"]["tmp_name"]);
// create image
$vImg = imagecreatefromstring($data);
//create big image
$dstImg = imagecreatetruecolor($nw, $nh);
imagealphablending($dstImg, false);
$trans_colour = imagecolorallocatealpha($dstImg, 0, 0, 0, 127);
imagefilledrectangle($dstImg, 0, 0, $w, $h, $trans_colour);
imagesavealpha($dstImg, true);
imagecopyresampled($dstImg, $vImg, 0, 0, $x, $y, $nw, $nh, $w, $h);
imagepng($dstImg, $big_image_path);
//create medium thumb
$dstImg1 = imagecreatetruecolor($nw1, $nh1);
imagealphablending($dstImg1, false);
$trans_colour1 = imagecolorallocatealpha($dstImg1, 0, 0, 0, 127);
imagefilledrectangle($dstImg1, 0, 0, $w, $h, $trans_colour1);
imagesavealpha($dstImg1, true);
imagecopyresampled($dstImg1, $vImg, 0, 0, $x, $y, $nw1, $nh1, $w, $h);
imagepng($dstImg1, $medium_image_path);
// create smallest thumb
$dstImg2 = imagecreatetruecolor($nw2, $nh2);
imagealphablending($dstImg2, false);
$trans_colour2 = imagecolorallocatealpha($dstImg2, 0, 0, 0, 127);
imagefilledrectangle($dstImg2, 0, 0, $w, $h, $trans_colour2);
imagesavealpha($dstImg2, true);
imagecopyresampled($dstImg2, $vImg, 0, 0, $x, $y, $nw2, $nh2, $w, $h);
imagepng($dstImg2, $small_image_path);
/*
* Database insertion
*/
$sql = "INSERT INTO tbl_inksand_product_gallery ("
. "Product_Id,Gallery_Image_Big,Gallery_Image_Medium,Gallery_Image_Thumb,"
. "Gallery_Status,Created_By,Created_Datetime"
. ") VALUES ("
. "'{$Product_Id}','{$big_image_path}','{$medium_image_path}','{$small_image_path}',"
. "'A','$Created_By','{$time}'"
. ")";
db_query($sql);
if (db_affected_rows() == 1) {
if (imagedestroy($dstImg)) {
$_SESSION['success'] = "Image uploaded successfully.";
echo "S-Image uploaded successfully<br>";
} else {
$_SESSION['alert'] = "Image not uploaded!!";
echo "S-Image not uploaded";
}
} else {
$_SESSION['alert'] = "Error in uploading image!!";
echo "E-Error in uploading image!!";
}
}
}
}
} else {
mkdir($upload_dir, 0777);
}
использование imagescale лучше, чем imagecopyresampled. Для изображения с измененным размером не требуется пустой ресурс изображения, требуется только два аргумента по сравнению с десятью, требуемыми для imagecopyresampled. Также обеспечивает лучшее качество при меньших размерах. Если вы используете PHP 5.5.18 или более раннюю версию или PHP 5.6.2 или более раннюю версию, вы должны указать высоту, которая является третьим аргументом, поскольку расчет соотношения сторон был неправильным.
$this->image = imagecreatefrompng($filename);
$scaled = imagescale($this->image, $width);
imagealphablending($scaled, false);
imagesavealpha($scaled, true);
imagepng($scaled, $filename);
Спасибо за это. У меня это сработало в конце 2020 года. Я использовал imagecreatetruecolor вместо imagecreatefrompng и пропустил часть imagescale.
что вы имеете в виду, говоря, что примеры вам не подходят?