繁体   English   中英

使用imagecopyresampled()PHP GD圆角透明_smooth_角

[英]Rounded transparent _smooth_ corners using imagecopyresampled() PHP GD

我需要一个脚本,在提供的图像上形成圆角透明角。 我找到了一个,它除了一件事之外它的效果很好:应用的角落看起来不平滑。 imageantialias()抛出致命错误,因为PHP在Debian上运行并且重新编译它不是一个选项。

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

  1. 准备图像;
  2. it to 10x size; 它到10倍大小;
  3. 用特殊颜色画角;
  4. 使颜色透明;
  5. 将图像缩小到原始大小

但问题出现了:结果图像的角落(在步骤5之后)是平滑的,但不是透明的 当在步骤4之后发送输出图像时(即在减小它的尺寸之前) - 一切都应该如此

这是负责使角落四舍五入的代码的一部分:

//    $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()建议 ,但没有结果。

请帮我完成这项工作。

PS这可能很有用:当将大型PNG上传到imgur.com时,它已将其转换为JPG ,因为您可以看到所有角落都填充了非常恢复的$ colorcode。

PS希望我不会因过度使用“放大”这个词而被禁止:)

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

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

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

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

毕竟,我写过这个函数

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

我用几个图像测试了它,它返回了每个bg颜色有光滑角落的图像。

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

产量

原始图像

在此输入图像描述

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

在此输入图像描述

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

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

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

函数返回GD对象false


功能适用于纯JPEG,GIF和PNG图像。 此外,它适用于透明的PNG和GIF。

...

/* rounded corner */
$radius = 20;

// find ghost color
do
{
  $r = rand(0, 255);
  $g = rand(0, 255);
  $b = rand(0, 255);
} while (imagecolorexact($img_resource, $r, $g, $b) < 0);
$ghost_color = imagecolorallocate($img_resource, $r, $g, $b);

imagearc($img_resource, $radius-1, $radius-1, $radius*2, $radius*2, 180, 270, $ghost_color);
imagefilltoborder($img_resource, 0, 0, $ghost_color, $ghost_color);
imagearc($img_resource, $img_width-$radius, $radius-1, $radius*2, $radius*2, 270, 0, $ghost_color);
imagefilltoborder($img_resource, $img_width-1, 0, $ghost_color, $ghost_color);
imagearc($img_resource, $radius-1, $img_height-$radius, $radius*2, $radius*2, 90, 180, $ghost_color);
imagefilltoborder($img_resource, 0, $img_height-1, $ghost_color, $ghost_color);
imagearc($img_resource, $img_width-$radius, $img_height-$radius, $radius*2, $radius*2, 0, 90, $ghost_color);
imagefilltoborder($img_resource, $img_width-1, $img_height-1, $ghost_color, $ghost_color);

imagecolortransparent($img_resource, $ghost_color);

...

试试这个......

来自@ Wh1T3h4Ck5的改进代码。 此功能可以拍摄图像并为其制作圆角而不会浪费内存。 它也必须在巨大的图像上更快地工作。 例如,1024 * 1024图像需要原始代码中的400MB临时图像。 现在只有230 KB。 (如果你使用半径10 px)。

函数取GD图像对象,半径为px并返回GD图像对象。 目前它与原始GD图像对象相同。

函数假设图像的大小从半径开始变大。 确切地说,任何一方都需要从($radius + 2)*2更大(或相等)。

此功能imagealphablending此图像的imagealphablending设置为true 如果您需要保存到png,请不要忘记将imagesavealpha设置为true

function roundCorners($source, $radius) {
    $ws = imagesx($source);
    $hs = imagesy($source);

    $corner = $radius + 2;
    $s = $corner*2;

    $src = imagecreatetruecolor($s, $s);
    imagecopy($src, $source, 0, 0, 0, 0, $corner, $corner);
    imagecopy($src, $source, $corner, 0, $ws - $corner, 0, $corner, $corner);
    imagecopy($src, $source, $corner, $corner, $ws - $corner, $hs - $corner, $corner, $corner);
    imagecopy($src, $source, 0, $corner, 0, $hs - $corner, $corner, $corner);

    $q = 8; # 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);

    $ns = $s * $q;

    $img = imagecreatetruecolor($ns, $ns);
    $alphacolor = imagecolorallocatealpha($img, $r, $g, $b, 127);
    imagealphablending($img, false);
    imagefilledrectangle($img, 0, 0, $ns, $ns, $alphacolor);

    imagefill($img, 0, 0, $alphacolor);
    imagecopyresampled($img, $src, 0, 0, 0, 0, $ns, $ns, $s, $s);
    imagedestroy($src);

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

    # resize image down
    $dest = imagecreatetruecolor($s, $s);
    imagealphablending($dest, false);
    imagefilledrectangle($dest, 0, 0, $s, $s, $alphacolor);
    imagecopyresampled($dest, $img, 0, 0, 0, 0, $s, $s, $ns, $ns);
    imagedestroy($img);

    # output image
    imagealphablending($source, false);
    imagecopy($source, $dest, 0, 0, 0, 0, $corner, $corner);
    imagecopy($source, $dest, $ws - $corner, 0, $corner, 0, $corner, $corner);
    imagecopy($source, $dest, $ws - $corner, $hs - $corner, $corner, $corner, $corner, $corner);
    imagecopy($source, $dest, 0, $hs - $corner, 0, $corner, $corner, $corner);
    imagealphablending($source, true);
    imagedestroy($dest);

    return $source;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM