如何在 PHP 中调整具有透明度的 png 大小?
Posted
技术标签:
【中文标题】如何在 PHP 中调整具有透明度的 png 大小?【英文标题】:How do I resize pngs with transparency in PHP? 【发布时间】:2010-09-21 17:01:51 【问题描述】:我正在尝试在 php 中调整具有透明背景的 png 大小,而我在网上找到的代码示例对我不起作用。这是我正在使用的代码,非常感谢您的建议!
$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 大小时背景颜色变为黑色。
【问题讨论】:
示例不适合您是什么意思? 【参考方案1】:据我所知,您需要将混合模式设置为 false
,并将保存 alpha 通道标志设置为 true
在执行 imagecolorallocatealpha()
<?php
/**
* https://***.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
【讨论】:
答案是完全不相关的,但这是调整透明度的正确方法。 这绝对是创建/复制透明 PNG 图像的正确方法。 @RyanDoherty 如果这不是答案,那么您能提供您的解决方案吗? 这对我也不起作用...背景保持黑色。当我执行 imagecopyresampled 时,如果使用前面的命令是透明的,它也会再次变黑... 从一百万种不同的答案和建议中尝试了一百万种不同的方法,这是唯一有效的方法。谢谢@Dycey【参考方案2】:还需要用透明颜色填充新图像(如 Dycey 编码,但我猜忘了提及 :)),而不仅仅是“战略”保存本身。
IIRC,您还需要确保 PNG 是 24 位的,即真彩色,而不是 8 位以避免错误行为。
【讨论】:
【参考方案3】:旧线程,但以防万一 - 如果您正确命名,Dycey 的示例应该可以工作。这是我的图像大小调整类中使用的修改版本。请注意检查以确保已定义 imagecolorallocatealpha(),如果您使用的是 GD ,则不会这样做
/**
* 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 调用的。这是一个错误。【参考方案4】:这对我也不起作用:( 这是我的解决方案.. 但我也得到黑色背景,图像不透明
<?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" ?>" />
【讨论】:
【参考方案5】:完整示例。请注意,对于在互联网上找到的一些 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
【讨论】:
【参考方案6】:这是一个适合我的最终解决方案。
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;
【讨论】:
【参考方案7】:这可能与较新版本的 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
就够了,谢谢;)【参考方案8】:
这是适用于 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);
【讨论】:
【参考方案9】:上述解决方案也不适合我。这就是我发现解决问题的方法。
// 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);
【讨论】:
【参考方案10】:与 imagecopyresampled 相比,使用 imagescale 效果更好。调整大小的图像不需要空图像资源,与 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
部分。【参考方案11】:
您可以简单地使用 imagescale() 调整图像大小 这段代码对我来说很好用:
$image = imagescale($image, 720, -1, IMG_BICUBIC);
imagepng($image);
【讨论】:
以上是关于如何在 PHP 中调整具有透明度的 png 大小?的主要内容,如果未能解决你的问题,请参考以下文章
如何改进我的 php 图像调整器以支持 alpha png 和透明 GIF
如何在opencv python中调整PNG图像的大小? [复制]
带有透明PNG的imagetruecolortopalette的PHP错误结果