Rounded transparent _smooth_ corners using imagecopyresampled() PHP GD

后端 未结 3 527
隐瞒了意图╮
隐瞒了意图╮ 2020-12-09 06:14

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. Th

3条回答
  •  半阙折子戏
    2020-12-09 06:28

    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.

    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
      }
    

    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');
    

    Output

    Original image

    enter image description here

    IN BROWSER (Same png file 'test.png')

    enter image description here

    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)

      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;
        }
    

    Function returns GD object or false.


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

提交回复
热议问题