使用.png、.gif或.jpg文件给另一个.png、.gif或.jpg文件添加水印

3
我正在尝试编写一个函数,可以在任何图像(.png、.jpg或.gif)上打水印,并且水印图像也可以是这些格式之一。我希望两个图像都保留透明度。我不关心gif动画。不幸的是,水印在不应该透明的地方变得透明,并且在应该透明的地方并没有完全透明。我使用了一些随机可用的图像来测试此脚本,我的结果看起来像这样:
代码如下:
  function watermark_get_left()
  {
    return NCFG_TEMPLATE_DIR . 'images/watermark_left.png';
  }

  function watermark_get_right()
  {
    return NCFG_TEMPLATE_DIR . 'images/watermark_right.png';
  }

  function create_img($path, $type)
  {
    switch($type)
    {
      case NCFG_IMAGE_JPG:
        $img = imagecreatefromjpeg($path);
        return $img;
      case NCFG_IMAGE_GIF:
        $img = imagecreatefromgif($path);
        return $img;
      case NCFG_IMAGE_PNG:
        $img = imagecreatefrompng($path);
        imagealphablending($img, false);
        imagesavealpha($img, true);
        return $img;
      default:
        return FALSE;
    }
  }

  function img_transparency($new_img, $img, $type)
  {
    if($type == NCFG_IMAGE_GIF)
    {
      $transparent_index = imagecolortransparent($img);

      if($transparent_index != -1)
      {
        $transparent_color = imagecolorsforindex($img, $transparent_index);
        $transparent_new = imagecolorallocate($new_img, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
        $transparent_new_index = imagecolortransparent($new_img, $transparent_new);
        imagefill($new_img, 0, 0, $transparent_new_index);
      }
    }else if($type == NCFG_IMAGE_PNG){
      imagecolortransparent($new_img, imagecolorallocatealpha($new_img, 0, 0, 0, 127));
      imagealphablending($new_img, false);
      imagesavealpha($new_img, true);
    }
  }

  function image_watermark($path, $new_path, &$w_height)
  {
    $type = get_image_type($path);
    list($width, $height) = getimagesize($path);

    if(!($img = create_img($path, $type)))
    {
      return FALSE;
    }

    $l_path = watermark_get_left();
    $r_path = watermark_get_right();

    if($l_exists = file_exists($l_path))
    {
      $l_type = get_image_type($l_path);
      list($l_width, $l_height) = getimagesize($l_path);

      if(!($l_img = create_img($l_path, $l_type)))
      {
        return FALSE;
      }
    }

    if($r_exists = file_exists($r_path))
    {
      $r_type = get_image_type($r_path);
      list($r_width, $r_height) = getimagesize($r_path);

      if(!($r_img = create_img($r_path, $r_type)))
      {
        return FALSE;
      }
    }

    $w_height = max(($r_exists ? $r_height : 0), ($l_exists ? $l_height : 0));

    echo("w_height: $w_height<br/>");

    $new_width = $width;
    $new_height = $height + $w_height;

    $new_img = imagecreatetruecolor($new_width, $new_height);

    $bg_color = imagecolorallocate($new_img, 255,255,255);
    imagefilledrectangle($new_img, 0, $height, $new_width - 1, $new_height - 1, $bg_color);

    img_transparency($new_img, $img, $type);
    imagecopy($new_img, $img, 0, 0, 0, 0, $width, $height);

    if($l_exists)
    {
      imagecopy($new_img, $l_img, 0, $height, 0, 0, $l_width, $l_height);
    }

    if($r_exists)
    {
      imagecopy($new_img, $r_img, $new_width - $r_width, $height, 0, 0, $r_width, $r_height);
    }

    switch($type)
    {
      case NCFG_IMAGE_JPG:
        imagejpeg($new_img, $new_path);
        break;
      case NCFG_IMAGE_GIF:
        imagegif($new_img, $new_path);
        break;
      case NCFG_IMAGE_PNG:
        imagepng($new_img, $new_path, 9);
        break;
    }

    imagedestroy($new_img);
    imagedestroy($img);

    return TRUE;
  }

我也尝试了imagecopymerge,但是没有成功。我希望能得到任何关于此问题的帮助。
编辑:我的图片被显示在这里,与我预期的不同。水印图像在白色背景上看起来正确,但在其他任何背景上都不正确。

4
我希望这两张图片都保留透明度。我不关心透明度。 - mowwwalker
2
据我所知,水印应该是半透明的。因此,你不能使用jpg作为水印,因为它没有透明度。而且这真的很令人困惑:“我希望两个图像都保留透明度。我不在乎透明度。” 你到底想要还是不想要呢? - Francisco Presencia
2
抱歉,我想写的是“我不在意gif动画”……我已经做太久了。 - Neob91
我正在将水印嵌入到底部,在扩展图像的高度之后。 - Neob91
1
这个刷子非常适合将一幅透明图像复制到另一幅图像上,可以参考http://php.net/manual/en/function.imagesetbrush.php - 以我的经验,imagecopy等方法往往不能像人们预期的那样工作。 - Niko
谢谢Niko,这帮了我很多! :) 它终于可以工作了。 - Neob91
1个回答

1

您可以使用ImageMagick CLI来完成此操作。以下是一行命令:

composite -dissolve 50% -geometry +20+10 -gravity SouthWest watermark.png input.png output.png

这将在input.pngSouthWest角上,以+20, +10像素的偏移量和50%的不透明度放置watermark.png。您可以根据自己的喜好进行调整,并在PHP中使用shell_exec

shell_exec('composite ...');

参考资料: http://www.imagemagick.org/script/command-line-options.php

样本图片:

编辑: 如果您还想扩展原始图像的高度(例如增加20个像素),则需要先执行以下操作:

convert original.png -bordercolor transparent -border 0x20 -background transparent -gravity NorthWest -extent +0+20 input.png

很遗憾,我的服务器上没有安装ImageMagick。我也无权安装它。 - Neob91

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接