45

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のサイズを変更すると背景色が黒に変わることを意味していました。

4

11 に答える 11

85

私が知る限り、imagecolorallocatealpha() を実行する前にfalse、ブレンド モードを に設定し、アルファ チャンネルの保存フラグをに設定する必要があります。true

<?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 の場合、背景は黒になります。

于 2008-11-10T21:53:17.573 に答える
4

古いスレッドですが、念のため-名前を正しく指定すれば、Dyceyの例は機能するはずです。これが私の画像サイズ変更クラスで使用されている修正バージョンです。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);
            }
        }
    }
于 2009-10-31T20:44:02.947 に答える
4

これはおそらく 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);
于 2015-05-01T04:06:56.527 に答える
4

新しい画像を透明な色で塗りつぶすことも必要です(Dyceyがコード化したように、言及するのを忘れていたと思います:))、それ自体で「戦略的な」保存だけではありません。

IIRC では、バグのある動作を避けるために、PNG が 8 ビットではなく 24 ビット、つまりトゥルーカラーであることも確認する必要があります。

于 2008-11-10T23:26:35.407 に答える
4

imagescale を使用すると、imagecopyresampled よりも優れています。サイズ変更された画像に空の画像リソースは必要ありません。imagecopyresampled で必要な 10 個の引数と比較して、必要な引数は 2 つだけです。また、サイズが小さいほど品質が向上します。PHP 5.5.18 以前、または PHP 5.6.2 以前を使用している場合、アスペクト比の計算が正しくないため、3 番目の引数である高さを指定する必要があります。

$this->image =   imagecreatefrompng($filename);
$scaled = imagescale($this->image, $width);
imagealphablending($scaled, false);
imagesavealpha($scaled, true);
imagepng($scaled, $filename);
于 2019-03-25T16:33:09.380 に答える
2

これは、画像の透明度を維持しながら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);
}
于 2016-09-01T10:01:29.853 に答える
1

完全な例。インターネットで見つかった一部の 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
于 2013-07-02T13:33:00.603 に答える
0

上記の解決策も私にとってはうまくいきませんでした。これは、問題を解決するために私が見つけた方法です。

// 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);
}
于 2016-09-02T05:43:56.907 に答える