php - 使用 imagecopyresampled() PHP GD 圆角透明_平滑_角

标签 php png transparency gd rounded-corners

我需要一个脚本,它可以在提供的图像上制作圆角透明角。我找到了一个,除了一件事外效果很好:应用的角看起来不光滑。 imageantialias()PHP is running on Debian 后抛出 fatal error 并重新编译它不是一种选择。

我发现使这些角看起来平滑的技巧是使用 imagecopyresampled() 调整图像大小。如下所示:

  1. 准备图片;
  2. imagecopyresample 到 10 倍大小;
  3. 用特殊颜色画角;
  4. 使该颜色透明;
  5. 将图片缩小到原来的大小

但问题来了:结果图像的角(在第 5 步之后)是 smooth, but not transparent .在第 4 步之后发送以输出图像时(即在减小其大小之前)– everything's as it should be .

下面是负责使角变圆的代码部分:

    //    $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()作为advised , 但没有结果。

请帮助我完成这项工作。

附言这可能有用:上传时 large PNG到 imgur.com 它有它 converted to JPG正如您所看到的,所有角落都充满了经过修复的 $colorcode。

附言希望我不会因为过度使用“扩大”这个词而被禁止:)

最佳答案

经过几个小时的测试并将我的头撞到墙上,我想我找到了解决方案。问题是关于使用 imagecolorallocate() 分配透明颜色。我第一眼没看懂。这是完全错误的做法。然而,imagecolorallocatealpha() 帮了我很多。

此外,在工作层上保存 alpha channel 之前,必须关闭 alpha 混合。但是,它必须在创建空白真彩色图像后立即完成,例如

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

这段代码是在缩小尺寸后在透明区域获得光滑角的关键。

毕竟这个函数是我写的

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

我用几张图片对其进行了测试,它返回的图片每个背景颜色都带有平滑的角。

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

输出

原图

enter image description here

在浏览器中(相同的 png 文件 'test.png')

enter image description here

它最终会返回完全透明的 alpha channel ,因此您可以在任何您想要的背景上使用该图像。

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

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

函数返回GD对象false


函数适用于纯 JPEG、GIF 和 PNG 图像。此外,它还适用于透明的 PNG 和 GIF。

关于php - 使用 imagecopyresampled() PHP GD 圆角透明_平滑_角,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5766865/

相关文章:

php - MySQL使用foreach将多个图像连接到相册并在页面上显示

wpf - 您如何覆盖WPF中父控件的不透明度?

C++ 位图资源 (RT_BITMAP) 和 PNG 图像格式

css - 如何制作透视效果的透明边 Angular ?

android - 背景透明,前景较暗

php - 从 php 应用程序写入/etc 的最安全方法?

php - 如何在 Shopify 中创建包含之前订购产品的列表?

php - MySQL 大圆距离(半正矢公式)

javascript - 如何获得 js png 修复以处理 ajax 调用

video - ffmpeg中带有png图像的电影