本文介绍了使用imagecopyresampled()倒圆角的透明_smooth_角PHP GD的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个脚本,用于在提供的图像上制作圆形的透明角.我发现了一个,除了一件事情外,它工作得很好:所应用的角看起来不光滑. imageantialias() 引发致命错误,因为 PHP在Debian上运行,并且无法重新编译.

I need a script which makes rounded transparent corners on supplied image. I've found one and it works good except the one thing: the applied corners do not look smooth. The imageantialias() throws Fatal Error since PHP is running on Debian and re-compiling it is not an option.

我发现使这些角看起来更光滑的技巧是使用 imagecopyresampled() 如下:

The trick I've found to make those corners look smooth is resizing the image with imagecopyresampled() as the following:

  1. 准备图像;
  2. imagecopy重新采样到10倍大小;
  3. 用特殊颜色画角;
  4. 使该颜色透明;
  5. 将图片缩小到原始大小
  1. prepare the image;
  2. imagecopyresample it to 10x size;
  3. draw corners with a special colour;
  4. make that color transparent;
  5. decrease the image to it's original size

但是问题来了:结果图像(在第5步之后)的角是光滑,但是不透明.在第4步之后(即减小其尺寸之前)发送以输出图像时– 所有内容应该是.

But here comes the problem: the corners of the result image (after step 5) are smooth, but not transparent. When sending to output the image after step 4 (i.e. before decreasing it's size) – everything's as it should be.

这是代码中负责使圆角变圆的部分:

Here's the part of the code responsible for making corners rounded:


    //    $dest = image resource


        $q=10;
        // making everything 10x bigger
        $new_width=$width*$q;
        $new_height=$height*$q;
        $radius=$radius*$q;

        $magnified=imagecreatetruecolor($new_width, $new_height);
        imagecopyresampled($magnified, $dest, 0,0, 0,0, $new_width,$new_height, ($new_width/$q),($new_height/$q));

        // picking the unique colour
        $found = false;
        while($found == false) {
            $r = rand(0, 255);
            $g = rand(0, 255);
            $b = rand(0, 255);
            if(imagecolorexact($magnified, $r, $g, $b) != (-1)) {
                $found = true;
            }
        }
        $colorcode = imagecolorallocate($magnified, $r, $g, $b);

            // drawing corners
            imagearc($magnified, $radius-1, $radius-1, $radius*2, $radius*2, 180, 270, $colorcode);
            imagefilltoborder($magnified, 0, 0, $colorcode, $colorcode);
            imagearc($magnified, $new_width-$radius, $radius-1, $radius*2, $radius*2, 270, 0, $colorcode);
            imagefilltoborder($magnified, $new_width-1, 0, $colorcode, $colorcode);
            imagearc($magnified, $radius-1, $new_height-$radius, $radius*2, $radius*2, 90, 180, $colorcode);
            imagefilltoborder($magnified, 0, $new_height-1, $colorcode, $colorcode);
            imagearc($magnified, $new_width-$radius, $new_height-$radius, $radius*2, $radius*2, 0, 90, $colorcode);
            imagefilltoborder($magnified, $new_width-1, $new_height-1, $colorcode, $colorcode);

        // making the unique colour transparent
        imagecolortransparent($magnified, $colorcode);

        // scaling down the enlarged image to it's original size
        // expecting corners to remain transparent
        imagecopyresampled($dest, $magnified, 0,0, 0,0, ($new_width/$q),($new_height/$q), $new_width,$new_height);
        // but they're not
        // sending $magnified to output for testing purposes
        $dest=$magnified;

    //    outputting $dest as image/png

因此,如您所见,当对放大的图像进行图像复制重新采样到其原始大小时,就会出现问题.透明的角用$colorcode颜色填充.我一直在玩 imagesavealpha() imagealphablending() 作为,但没有结果.

So as you can see, the problem occurs when enlarged image is being imagecopyresampled to it's original size. The transparent corners get filled with the $colorcode colour. I've been playing with imagesavealpha() and imagealphablending() as advised, but no result.

请帮助我完成这项工作.

Please help me to make this work.

P.S.这可能很有用:将大PNG 上传到imgur.com它转换为JPG 后,您会看到所有角落都充满了经过修复的$颜色代码.

P.S. This may be useful: when uploaded the large PNG to imgur.com it had it converted to JPG and as you can see all corners got filled with that very restored $colorcode.

P.S.希望我不会因滥用扩大"一词而被禁止使用:)

P.S. Hope I won't get banned for overusing the word "enlargement" :)

推荐答案

经过几个小时的测试并将我的头撞在墙上,我认为我已经找到了解决方案.问题在于使用imagecolorallocate()分配透明颜色.我没有一见钟情.这是完全错误的方法.但是,imagecolorallocatealpha()帮助了我很多.

After couple of hours of testing and kicking my head against the wall, I think I've found solution. Problem was about allocating transparent color using imagecolorallocate(). I did not get it at first sight. It was totally wrong approach. However, imagecolorallocatealpha() has helped me alot.

此外,在将Alpha通道保存到工作层之前,必须禁用Alpha混合.但是,必须在创建空白的真彩色图像后立即完成,例如

Also, alpha blending must be off before saving alpha channel on working layer. However, it must be done right after creating blank true-color image, like

  $im = imagecreatetruecolor($w, $h);
  $alphacolor = imagecolorallocatealpha($img, $r, $g, $b, 127);
  imagealphablending($im, false);
  imagesavealpha($im, true);

此代码是在调整大小后在透明区域获得平滑角的关键.

This code is a key for getting smooth corners in transparent area after resize-down.

毕竟,我已经编写了此函数

After all, I've wrote this function

  function imageCreateCorners($sourceImageFile, $radius) {
  # function body
  }

我已经用几张图像对其进行了测试,对于每种bg颜色,它返回的图像均具有平滑的角.

I've tested it with couple of images and it returned image with smooth corners for every bg color.

  imagepng(imageCreateCorners('jan_vesely_and_james_gist.jpg', 9), 'test.png');

输出

原始图片

它最终返回完全透明的Alpha通道,因此您可以在所需的每个背景上使用该图像.

It finally returns fully transparent alpha channel so you can use that image on every background you want.

我差点忘了发布功能代码:)

I almost forgot to post function code :)

  function imageCreateCorners($sourceImageFile, $radius) {
    # test source image
    if (file_exists($sourceImageFile)) {
      $res = is_array($info = getimagesize($sourceImageFile));
      }
    else $res = false;

    # open image
    if ($res) {
      $w = $info[0];
      $h = $info[1];
      switch ($info['mime']) {
        case 'image/jpeg': $src = imagecreatefromjpeg($sourceImageFile);
          break;
        case 'image/gif': $src = imagecreatefromgif($sourceImageFile);
          break;
        case 'image/png': $src = imagecreatefrompng($sourceImageFile);
          break;
        default:
          $res = false;
        }
      }

    # create corners
    if ($res) {

      $q = 10; # change this if you want
      $radius *= $q;

      # find unique color
      do {
        $r = rand(0, 255);
        $g = rand(0, 255);
        $b = rand(0, 255);
        }
      while (imagecolorexact($src, $r, $g, $b) < 0);

      $nw = $w*$q;
      $nh = $h*$q;

      $img = imagecreatetruecolor($nw, $nh);
      $alphacolor = imagecolorallocatealpha($img, $r, $g, $b, 127);
      imagealphablending($img, false);
      imagesavealpha($img, true);
      imagefilledrectangle($img, 0, 0, $nw, $nh, $alphacolor);

      imagefill($img, 0, 0, $alphacolor);
      imagecopyresampled($img, $src, 0, 0, 0, 0, $nw, $nh, $w, $h);

      imagearc($img, $radius-1, $radius-1, $radius*2, $radius*2, 180, 270, $alphacolor);
      imagefilltoborder($img, 0, 0, $alphacolor, $alphacolor);
      imagearc($img, $nw-$radius, $radius-1, $radius*2, $radius*2, 270, 0, $alphacolor);
      imagefilltoborder($img, $nw-1, 0, $alphacolor, $alphacolor);
      imagearc($img, $radius-1, $nh-$radius, $radius*2, $radius*2, 90, 180, $alphacolor);
      imagefilltoborder($img, 0, $nh-1, $alphacolor, $alphacolor);
      imagearc($img, $nw-$radius, $nh-$radius, $radius*2, $radius*2, 0, 90, $alphacolor);
      imagefilltoborder($img, $nw-1, $nh-1, $alphacolor, $alphacolor);
      imagealphablending($img, true);
      imagecolortransparent($img, $alphacolor);

      # resize image down
      $dest = imagecreatetruecolor($w, $h);
      imagealphablending($dest, false);
      imagesavealpha($dest, true);
      imagefilledrectangle($dest, 0, 0, $w, $h, $alphacolor);
      imagecopyresampled($dest, $img, 0, 0, 0, 0, $w, $h, $nw, $nh);

      # output image
      $res = $dest;
      imagedestroy($src);
      imagedestroy($img);
      }

    return $res;
    }

函数返回 GD对象 false .

该功能适用​​于纯JPEG,GIF和PNG图像.此外,它与透明的PNG和GIF配合使用也很不错.

Function works with solid JPEG, GIF and PNG images. Also, it works great with transparent PNGs and GIFs.

这篇关于使用imagecopyresampled()倒圆角的透明_smooth_角PHP GD的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-31 04:41