上传和调整 Png 大小会产生黑色背景图像

Posted

技术标签:

【中文标题】上传和调整 Png 大小会产生黑色背景图像【英文标题】:Uploading and resizing Png produces a black background image 【发布时间】:2015-08-12 12:39:15 【问题描述】:

我正在使用以下类来裁剪、调整大小和上传图像。但是当我尝试上传文件时,它会生成一个黑色背景的 png 图像。

我尝试了很多方法,例如 imageAlphaBlending 和 imageSaveAlpha,但都没有解决我的问题

我正在使用此链接中的 ImageManipulator.php https://gist.github.com/philBrown/880506

请告诉我如何解决这个问题。谢谢你

`

/**
 * @var int
 */
protected $height;

/**
 * @var resource
 */
protected $image;

/**
 * Image manipulator constructor
 * 
 * @param string $file OPTIONAL Path to image file or image data as string
 * @return void
 */
public function __construct($file = null)

    if (null !== $file) 
        if (is_file($file)) 
            $this->setImageFile($file);
         else 
            $this->setImageString($file);
        
    


/**
 * Set image resource from file
 * 
 * @param string $file Path to image file
 * @return ImageManipulator for a fluent interface
 * @throws InvalidArgumentException
 */
public function setImageFile($file)

    if (!(is_readable($file) && is_file($file))) 
        throw new InvalidArgumentException("Image file $file is not readable");
    

    if (is_resource($this->image)) 
        imagedestroy($this->image);
    

    list ($this->width, $this->height, $type) = getimagesize($file);

    switch ($type) 
        case IMAGETYPE_GIF  :
            $this->image = imagecreatefromgif($file);
            break;
        case IMAGETYPE_JPEG :
            $this->image = imagecreatefromjpeg($file);
            break;
        case IMAGETYPE_PNG  :
            $this->image = imagecreatefrompng($file);
            break;
        default             :
            throw new InvalidArgumentException("Image type $type not supported");
    

    return $this;


/**
 * Set image resource from string data
 * 
 * @param string $data
 * @return ImageManipulator for a fluent interface
 * @throws RuntimeException
 */
public function setImageString($data)

    if (is_resource($this->image)) 
        imagedestroy($this->image);
    

    if (!$this->image = imagecreatefromstring($data)) 
        throw new RuntimeException('Cannot create image from data string');
    
    $this->width = imagesx($this->image);
    $this->height = imagesy($this->image);
    return $this;


/**
 * Resamples the current image
 *
 * @param int  $width                New width
 * @param int  $height               New height
 * @param bool $constrainProportions Constrain current image proportions when resizing
 * @return ImageManipulator for a fluent interface
 * @throws RuntimeException
 */
public function resample($width, $height, $constrainProportions = true)

    if (!is_resource($this->image)) 
        throw new RuntimeException('No image set');
    
    if ($constrainProportions) 
        if ($this->height >= $this->width) 
            $width  = round($height / $this->height * $this->width);
         else 
            $height = round($width / $this->width * $this->height);
        
    
    $temp = imagecreatetruecolor($width, $height);
    imagecopyresampled($temp, $this->image, 0, 0, 0, 0, $width, $height, $this->width, $this->height);
    return $this->_replace($temp);


/**
 * Enlarge canvas
 * 
 * @param int   $width  Canvas width
 * @param int   $height Canvas height
 * @param array $rgb    RGB colour values
 * @param int   $xpos   X-Position of image in new canvas, null for centre
 * @param int   $ypos   Y-Position of image in new canvas, null for centre
 * @return ImageManipulator for a fluent interface
 * @throws RuntimeException
 */
public function enlargeCanvas($width, $height, array $rgb = array(), $xpos = null, $ypos = null)

    if (!is_resource($this->image)) 
        throw new RuntimeException('No image set');
    


    $width = max($width, $this->width);
    $height = max($height, $this->height);

    $temp = imagecreatetruecolor($width, $height);
    if (count($rgb) == 3) 
        $bg = imagecolorallocate($temp, $rgb[0], $rgb[1], $rgb[2]);
        imagefill($temp, 0, 0, $bg);
    

    if (null === $xpos) 
        $xpos = round(($width - $this->width) / 2);
    
    if (null === $ypos) 
        $ypos = round(($height - $this->height) / 2);
    

    imagecopy($temp, $this->image, (int) $xpos, (int) $ypos, 0, 0, $this->width, $this->height);
    return $this->_replace($temp);


/**
 * Crop image
 * 
 * @param int|array $x1 Top left x-coordinate of crop box or array of coordinates
 * @param int       $y1 Top left y-coordinate of crop box
 * @param int       $x2 Bottom right x-coordinate of crop box
 * @param int       $y2 Bottom right y-coordinate of crop box
 * @return ImageManipulator for a fluent interface
 * @throws RuntimeException
 */
public function crop($x1, $y1 = 0, $x2 = 0, $y2 = 0)

    if (!is_resource($this->image)) 
        throw new RuntimeException('No image set');
    
    if (is_array($x1) && 4 == count($x1)) 
        list($x1, $y1, $x2, $y2) = $x1;
    

    $x1 = max($x1, 0);
    $y1 = max($y1, 0);

    $x2 = min($x2, $this->width);
    $y2 = min($y2, $this->height);

    $width = $x2 - $x1;
    $height = $y2 - $y1;

    $temp = imagecreatetruecolor($width, $height);
    imagecopy($temp, $this->image, 0, 0, $x1, $y1, $width, $height);

    return $this->_replace($temp);


/**
 * Replace current image resource with a new one
 * 
 * @param resource $res New image resource
 * @return ImageManipulator for a fluent interface
 * @throws UnexpectedValueException
 */
protected function _replace($res)

    if (!is_resource($res)) 
        throw new UnexpectedValueException('Invalid resource');
    
    if (is_resource($this->image)) 
        imagedestroy($this->image);
    
    $this->image = $res;
    $this->width = imagesx($res);
    $this->height = imagesy($res);
    return $this;


/**
 * Save current image to file
 * 
 * @param string $fileName
 * @return void
 * @throws RuntimeException
 */
public function save($fileName, $type = IMAGETYPE_JPEG)

    $dir = dirname($fileName);
    if (!is_dir($dir)) 
        if (!mkdir($dir, 0755, true)) 
            throw new RuntimeException('Error creating directory ' . $dir);
        
    

    try 
        switch ($type) 
            case IMAGETYPE_GIF  :
                if (!imagegif($this->image, $fileName)) 
                    throw new RuntimeException;
                
                break;
            case IMAGETYPE_PNG  :
                if (!imagepng($this->image, $fileName)) 
                    throw new RuntimeException;
                
                break;
            case IMAGETYPE_JPEG :
            default             :
                if (!imagejpeg($this->image, $fileName, 95)) 
                    throw new RuntimeException;
                
        
     catch (Exception $ex) 
        throw new RuntimeException('Error saving image file to ' . $fileName);
    


/**
 * Returns the GD image resource
 *
 * @return resource
 */
public function getResource()

    return $this->image;


/**
 * Get current image resource width
 *
 * @return int
 */
public function getWidth()

    return $this->width;


/**
 * Get current image height
 *
 * @return int
 */
public function getHeight()

    return $this->height;

`

【问题讨论】:

echo "<script>alert('dfds')</script>"; 的加入感到好奇~ 仅仅是为了尝试调试吗?我猜想在创建 png 时会导致错误... 对不起..我正在尝试调试。但这不是真正的问题。请忽略此行 请任何人告诉我一个解决方案。 您是否更改了图像类的副本以合并其他用户建议的修复(朝向页面底部)? 【参考方案1】:

我终于找到了解决这个问题的办法

我们需要修改重采样和这些额外的行

`$temp = imagecreatetruecolor($width, $height);

// PNG/GIF Transparency
imagealphablending($temp, false);
imagesavealpha($temp,true);
$transparent = imagecolorallocatealpha($temp, 255, 255, 255, 127);
imagefilledrectangle($temp, 0, 0, $width, $height, $transparent);

imagecopyresampled($temp, $this->image, 0, 0, 0, 0, $width, $height, $this->width, $this->height);`

在保存功能中,我们还需要添加一些额外的行,例如 case IMAGETYPE_PNG : imagealphablending($this->image, false); imagesavealpha($this->image,true);

这将解决问题。感谢大家为解决这个问题所做的努力。

【讨论】:

【参考方案2】:

正确的做法是在你的 setImageFile 函数中,在$this->image = imagecreatefrompng($file); 之后添加这些行:

imageAlphaBlending($this->image, true);
imageSaveAlpha($this-image, true);

另外,在保存函数内部,case IMAGETYPE_PNG : 之后添加:

header('Content-Type: image/png');

【讨论】:

对不起,我回答错了问题。真对不起。我编辑了答案,现在应该可以正常工作了

以上是关于上传和调整 Png 大小会产生黑色背景图像的主要内容,如果未能解决你的问题,请参考以下文章

使用 php Imagick 保留背景调整 PNG 的大小

调整透明图像(UIImage)的大小而不获得黑色背景

将矩形图像调整为正方形,保持比例并用黑色填充背景

调整大小以适合盒子并将“空”部分的背景设置为黑色

如何使用 GraphicsMagick 从图像中裁剪/调整背景/边框的大小

自定义PNG翻转功能在图像上输出黑色背景