使用php将jpg保存为透明png

时间:2013-01-10 22:54:34

标签: php image-processing gd

我创建了一个函数,它根据参数以不同的方式处理图像。我在函数中有一些注释可以解释一下。

当我拍摄jpg图像并将其另存为png时,一切都有效。我刚检查过,即使我使用imagepng()但是使用扩展名.jpg保存它,图像会在正确调整大小时显示,但带有.jpg扩展名。但是,如果我上传相同的.jpg图像,使用imagepng()并以.png扩展名保存,我会在调整大小后以png格式获得预期宽度和高度的图像,扩展名为.png 。虽然整个图像是100%透明的,但左上角有一个1像素乘1像素的黑色像素。

如果有人能看到这个并看看他们是否看到我遗失的东西,我将不胜感激。我相信1px X 1px来自我用于imagefill()的点,但我不明白为什么;它应该像图像的其余部分一样填充透明。

这是我的功能:

if(!function_exists("upload")){
    //$image = $image file name
    //$width = intended width of resized image, if 0 it will proportion to height, overrides proportion
    //$height = intended width of resized image, if 0 it will proportion to width, overrides proportion
    //$proportion = 2,1,0;
    //------ 2 = Preserve proportions while adding a border to fill width and height  
    //------ 1 = retain proportion to fit within both given width and height
    //------ 0 = disregard proportions and resize to the exact width and height
    function upload($image, $width, $height, $proportion){
        // IS GD HERE?

        $gdv = get_gd_info();

        if (!$gdv){ 
            return FALSE;
        }

        // GET AN IMAGE THING

        $ext = trim(strtolower(end(explode('.', $image))));

        list($imageX, $imageY, $type) = getimagesize($image);   //gets information about new server image

        // GET THE LESSER OF THE RATIO OF THUMBNAIL H OR W DIMENSIONS
        $ratio_w = ($width / $imageX);
        $ratio_h = ($height / $imageY);
        $ratio   = ($ratio_w < $ratio_h) ? $ratio_w : $ratio_h;     

        if($width == 0){

            if($imageY > $height){
                $newHeight = $height;
                $newWidth = ($height/$imageY) * $imageX;    
            }else{
                $newHeight = $imageY;
                $newWidth = $imageX;    
            }

            $width = $newWidth;
            $height = $newHeight;

            // COMPUTE THUMBNAIL IMAGE CENTERING OFFSETS
            $fromMidX = 0;
            $fromMidY = 0;

        }elseif($height == 0){

            if ($imageX > $width){
                $newWidth = $width;
                $newHeight = ($width/$imageX) * $imageY;
            }else{
                $newHeight = $imageY;
                $newWidth = $imageX;    
            }

            $width = $newWidth;
            $height = $newHeight;

            // COMPUTE THUMBNAIL IMAGE CENTERING OFFSETS
            $fromMidX = 0;
            $fromMidY = 0;

        }elseif($proportion == 2){

            // COMPUTE THUMBNAIL IMAGE DIMENSIONS
            $newWidth = $imageX * $ratio;
            $newHeight = $imageY * $ratio;

            // COMPUTE THUMBNAIL IMAGE CENTERING OFFSETS
            $fromMidX = ($width - $newWidth) / 2.0;
            $fromMidY = ($height - $newHeight) / 2.0;

        }elseif($proportion == 1){

            if ($imageX > $width){
                $newHeight = ($width/$imageX) * $imageY;
                $newWidth = $width;
            }
            if ($imageY > $height){
                $newHeight = $height;
                $newWidth = ($height/$imageY) * $imageX;
            }

            $fromMidY = 0;
            $fromMidX = 0;

        }elseif($proportion == 0){

            $newWidth = $width;
            $newHeight = $height;

            $fromMidY = 0;
            $fromMidX = 0;          
        }

        switch(strtoupper($ext))
        {
            case 'JPG' :
            case 'JPEG' :
                $source = imagecreatefromjpeg($image);
                break;

            case 'PNG' :
                $source = imagecreatefrompng($image);

                break;

            default : die("UNKNOWN IMAGE TYPE: $image");
        }

        // WHICH FUNCTIONS CAN RESIZE / RESAMPLE THE IMAGE?
        if ($gdv >= 2)
        {

            // IF GD IS AT LEVEL 2 OR ABOVE
            $target = imagecreatetruecolor($width, $height);
            $color = imagecolorallocatealpha($target, 0, 0, 0, 127); 

            imagefill($target, 0, 0, $color);

            imagesavealpha($target, TRUE);


            imagecopyresampled ($target, $source, $fromMidX, $fromMidY, 0, 0, $newWidth, $newHeight, $imageX, $imageY);

        }
        else
        {
            // IF GD IS AT A LOWER REVISION LEVEL
            $target = imagecreate($width, $height);
            imagesavealpha($target, TRUE);
                $empty = imagecolorallocatealpha($thumb,0x00,0x00,0x00,127);
                imagefill($target, 0, 0, $empty);
            imagecopyresized($target, $source, $fromMidX, $fromMidY, 0, 0, $newWidth, $newHeight, $imageX, $imageY);
        }

        // SHARPEN THE PIC
        $sharpenMatrix = array
        ( array( -1.2, -1, -1.2 )
        , array( -1,   20, -1 )
        , array( -1.2, -1, -1.2 )
        )
        ;
        $divisor = array_sum(array_map('array_sum', $sharpenMatrix));
        $offset  = 0;
        imageconvolution($target, $sharpenMatrix, $divisor, $offset);

        if(imagepng($target, $image,9)){

            imagedestroy($target);
        }else{

        }

        return $image;  
    }
}
编辑1:我想我应该注意到我正在上传.jpg图像(例如:100px X 200px)并将它们转换为.png(例如:400px X 200px)但保留图像的比例以适应完美地位于目的地的中心.png。所以我的中心图像为400px X 200px .p​​ng,左右为100px,应该是透明的。这样它很适合滑块而没有纯色作为填充。所以我调用我的函数的例子是upload($image, 400, 200, 2)

1 个答案:

答案 0 :(得分:0)

我弄清楚问题是什么。决定是否应该使用imagecreatefromjpegimagecreatefrompng的代码部分错误地偏离了传递图像的扩展名而不是其mime类型。我把它换成了这个:

switch($type)
        {
            case '2' :
                $source = imagecreatefromjpeg($image);
                break;
            case '3' :
                $source = imagecreatefrompng($image);
                break;
            default : die("UNKNOWN IMAGE TYPE: $image");
        }

其中$type来自我在那里的行

list($imageX, $imageY, $type) = getimagesize($image);

所以这一切的功能是:

if(!function_exists("upload")){
    //$image = $image file name
    //$width = intended width of resized image, if 0 it will proportion to height, overrides proportion
    //$height = intended width of resized image, if 0 it will proportion to width, overrides proportion
    //$proportion = 2,1,0;
    //------ 2 = Preserve proportions while adding a border to fill width and height  
    //------ 1 = retain proportion to fit within both given width and height
    //------ 0 = disregard proportions and resize to the exact width and height


    function upload($image, $width, $height, $proportion){
        // IS GD HERE?

        $gdv = get_gd_info();

        if (!$gdv){ 
            return FALSE;
        }

        // GET AN IMAGE THING

        $ext = trim(strtolower(end(explode('.', $image))));

        list($imageX, $imageY, $type) = getimagesize($image);   //gets information about new server image

        // GET THE LESSER OF THE RATIO OF THUMBNAIL H OR W DIMENSIONS
        $ratio_w = ($width / $imageX);
        $ratio_h = ($height / $imageY);
        $ratio   = ($ratio_w < $ratio_h) ? $ratio_w : $ratio_h;     

        if($width == 0){

            if($imageY > $height){
                $newHeight = $height;
                $newWidth = ($height/$imageY) * $imageX;    
            }else{
                $newHeight = $imageY;
                $newWidth = $imageX;    
            }

            $width = $newWidth;
            $height = $newHeight;

            // COMPUTE THUMBNAIL IMAGE CENTERING OFFSETS
            $fromMidX = 0;
            $fromMidY = 0;

        }elseif($height == 0){

            if ($imageX > $width){
                $newWidth = $width;
                $newHeight = ($width/$imageX) * $imageY;
            }else{
                $newHeight = $imageY;
                $newWidth = $imageX;    
            }

            $width = $newWidth;
            $height = $newHeight;

            // COMPUTE THUMBNAIL IMAGE CENTERING OFFSETS
            $fromMidX = 0;
            $fromMidY = 0;

        }elseif($proportion == 2){

            // COMPUTE THUMBNAIL IMAGE DIMENSIONS
            $newWidth = $imageX * $ratio;
            $newHeight = $imageY * $ratio;

            // COMPUTE THUMBNAIL IMAGE CENTERING OFFSETS
            $fromMidX = ($width - $newWidth) / 2.0;
            $fromMidY = ($height - $newHeight) / 2.0;

        }elseif($proportion == 1){

            if ($imageX > $width){
                $newHeight = ($width/$imageX) * $imageY;
                $newWidth = $width;
            }
            if ($imageY > $height){
                $newHeight = $height;
                $newWidth = ($height/$imageY) * $imageX;
            }

            $fromMidY = 0;
            $fromMidX = 0;

        }elseif($proportion == 0){

            $newWidth = $width;
            $newHeight = $height;

            $fromMidY = 0;
            $fromMidX = 0;          
        }

        switch($type)
        {
            case '2' :
                $source = imagecreatefromjpeg($image);
                break;
            case '3' :
                $source = imagecreatefrompng($image);
                break;
            default : die("UNKNOWN IMAGE TYPE: $image");
        }

        // WHICH FUNCTIONS CAN RESIZE / RESAMPLE THE IMAGE?
        if ($gdv >= 2)
        {

            // IF GD IS AT LEVEL 2 OR ABOVE
            $target = imagecreatetruecolor($width, $height);
            $color = imagecolorallocatealpha($target, 0, 0, 0, 127); 
            imagefill($target, 0, 0, $color);
            imagesavealpha($target, TRUE);
            imagecopyresampled ($target, $source, $fromMidX, $fromMidY, 0, 0, $newWidth, $newHeight, $imageX, $imageY);

        }
        else
        {
            // IF GD IS AT A LOWER REVISION LEVEL
            $target = imagecreate($width, $height);
            imagesavealpha($target, TRUE);
                $empty = imagecolorallocatealpha($thumb,0x00,0x00,0x00,127);
                imagefill($target, 0, 0, $empty);
            imagecopyresized($target, $source, $fromMidX, $fromMidY, 0, 0, $newWidth, $newHeight, $imageX, $imageY);
        }

        // SHARPEN THE PIC
        $sharpenMatrix = array
        ( array( -1.2, -1, -1.2 )
        , array( -1,   20, -1 )
        , array( -1.2, -1, -1.2 )
        )
        ;
        $divisor = array_sum(array_map('array_sum', $sharpenMatrix));
        $offset  = 0;
        imageconvolution($target, $sharpenMatrix, $divisor, $offset);

        if(imagepng($target, $image,9)){
            imagedestroy($target);
        }
        return $image;
    }
}

示例调用将是:upload("path/to/image/on/server.png", 400, 200, 2) 图像路径可以是jpg或png mime类型。但扩展必须是.png。我想我可以把它变得更聪明,你可以有任何扩展,但是使用这个函数的当前代码对我来说更有意义。我想最终添加选项来打开或关闭透明度,而是使用纯色(如黑色),如果需要的话。随意使用和修改它。

有很好的hex2rgb / rgb2hex函数我计划用于此here