完美png图片添加水印类

被添加水印图片和水印图片都可以是png,保证透明无色背景,可调节透明度

<?php
class Imgshuiyin{
/* 缩略图相关常量定义 */
const THUMB_SCALING = 1; //常量,标识缩略图等比例缩放类型
const THUMB_FILLED = 2; //常量,标识缩略图缩放后填充类型
const THUMB_CENTER = 3; //常量,标识缩略图居中裁剪类型
const THUMB_NORTHWEST = 4; //常量,标识缩略图左上角裁剪类型
const THUMB_SOUTHEAST = 5; //常量,标识缩略图右下角裁剪类型
const THUMB_FIXED = 6; //常量,标识缩略图固定尺寸缩放类型
/* 水印相关常量定义 */
const WATER_NORTHWEST = 1; //常量,标识左上角水印
const WATER_NORTH = 2; //常量,标识上居中水印
const WATER_NORTHEAST = 3; //常量,标识右上角水印
const WATER_WEST = 4; //常量,标识左居中水印
const WATER_CENTER = 5; //常量,标识居中水印
const WATER_EAST = 6; //常量,标识右居中水印
const WATER_SOUTHWEST = 7; //常量,标识左下角水印
const WATER_SOUTH = 8; //常量,标识下居中水印
const WATER_SOUTHEAST = 9; //常量,标识右下角水印
/* 翻转相关常量定义 */
const FLIP_X = 1; //X轴翻转
const FLIP_Y = 2; //Y轴翻转
/**
* 图像资源对象
*
* @var resource
*/
protected $im;
protected function __construct(\SplFileInfo $file)
{
//获取图像信息
$info = @getimagesize($file->getPathname());

//检测图像合法性
if (false === $info || (IMAGETYPE_GIF === $info[2] && empty($info['bits']))) {
//throw new ImageException('Illegal image file');
}

//设置图像信息
$this->info = [
'width' => $info[0],
'height' => $info[1],
'type' => image_type_to_extension($info[2], false),
'mime' => $info['mime'],
];

//打开图像
if ('gif' == $this->info['type']) {
//$this->gif = new Gif($file->getPathname());
//$this->im = @imagecreatefromstring($this->gif->image());
} else {
$fun = "imagecreatefrom{$this->info['type']}";
$this->im = @$fun($file->getPathname());
}

if (empty($this->im)) {
//throw new ImageException('Failed to create image resources!');
}

}
/**
* 打开一个图片文件
* @param \SplFileInfo|string $file
* @return Image
*/
public static function open($file)
{
if (is_string($file)) {
$file = new \SplFileInfo($file);
}
if (!$file->isFile()) {
//throw new ImageException('image file not exist');
}
return new self($file);
}
/**
* 添加水印
*
* @param string $source 水印图片路径
* @param int $locate 水印位置
* @param int $alpha 透明度
* @return $this
*/
public function water($source, $locate = 5, $alpha = 100)
{
if (!is_file($source)) {
// throw new ImageException('水印图像不存在');
}
//获取水印图像信息
$info = getimagesize($source);
if (false === $info || (IMAGETYPE_GIF === $info[2] && empty($info['bits']))) {
//throw new ImageException('非法水印文件');
}
//创建水印图像资源
$fun = 'imagecreatefrom' . image_type_to_extension($info[2], false);
$water = $fun($source);
//设定水印图像的混色模式
imagealphablending($water, true);
/* 设定水印位置 */
switch ($locate) {
/* 右下角水印 */
case self::WATER_SOUTHEAST:
$x = $this->info['width'] - $info[0];
$y = $this->info['height'] - $info[1];
break;
/* 左下角水印 */
case self::WATER_SOUTHWEST:
$x = 0;
$y = $this->info['height'] - $info[1];
break;
/* 左上角水印 */
case self::WATER_NORTHWEST:
$x = $y = 0;
break;
/* 右上角水印 */
case self::WATER_NORTHEAST:
$x = $this->info['width'] - $info[0];
$y = 0;
break;
/* 居中水印 */
case self::WATER_CENTER:
$x = ($this->info['width'] - $info[0]) / 2;
$y = ($this->info['height'] - $info[1]) / 2;
break;
/* 下居中水印 */
case self::WATER_SOUTH:
$x = ($this->info['width'] - $info[0]) / 2;
$y = $this->info['height'] - $info[1];
break;
/* 右居中水印 */
case self::WATER_EAST:
$x = $this->info['width'] - $info[0];
$y = ($this->info['height'] - $info[1]) / 2;
break;
/* 上居中水印 */
case self::WATER_NORTH:
$x = ($this->info['width'] - $info[0]) / 2;
$y = 0;
break;
/* 左居中水印 */
case self::WATER_WEST:
$x = 0;
$y = ($this->info['height'] - $info[1]) / 2;
break;
default:
/* 自定义水印坐标 */
if (is_array($locate)) {
list($x, $y) = $locate;
} else {
// throw new ImageException('不支持的水印位置类型');
}
}
do {
//添加水印
$src = imagecreatetruecolor($info[0], $info[1]);
// 调整默认颜色
$color = imagecolorallocate($src, 0, 0, 0);
//设置透明
imagecolortransparent($src,$color);
imagefill($src, 0, 0, $color);
imagecopy($src, $this->im, 0, 0, $x, $y, $info[0], $info[1]);
imagecopy($src, $water, 0, 0, 0, 0, $info[0], $info[1]);
imagecopymerge($this->im, $src, $x, $y, 0, 0, $info[0], $info[1], $alpha);
//销毁零时图片资源
imagedestroy($src);
} while (!empty($this->gif) && $this->gifNext());
//销毁水印资源
imagedestroy($water);
return $this;
} /**
* 保存图像
* @param string $pathname 图像保存路径名称
* @param null|string $type 图像类型
* @param int $quality 图像质量
* @param bool $interlace 是否对JPEG类型图像设置隔行扫描
* @return $this
*/
public function save($pathname, $type = null, $quality = 80, $interlace = true)
{
//自动获取图像类型
if (is_null($type)) {
$type = $this->info['type'];
} else {
$type = strtolower($type);
}
//保存图像
if ('jpeg' == $type || 'jpg' == $type) {
//JPEG图像设置隔行扫描
imageinterlace($this->im, $interlace);
imagejpeg($this->im, $pathname, $quality);
} elseif ('gif' == $type && !empty($this->gif)) {
$this->gif->save($pathname);
} elseif ('png' == $type) {
//设定保存完整的 alpha 通道信息
imagesavealpha($this->im, true);
//ImagePNG生成图像的质量范围从0到9的
imagepng($this->im, $pathname, min((int) ($quality / 10), 9));
} else {
$fun = 'image' . $type;
$fun($this->im, $pathname);
}

return $this;
}
}

完美png图片添加水印类的更多相关文章

  1. Android--很实用的图片工具类

    import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; imp ...

  2. .net为图片添加水印(转) jpg png和gif格式

    .net为图片添加水印(转) jpg png和gif格式 .net为图片添加水印(转) jpg png和gif格式,转自csdn的hyde82,现在跟大家一起来分享下: 利 用.net中System. ...

  3. 神奇的canvas——巧用 canvas 为图片添加水印

    代码地址如下:http://www.demodashi.com/demo/11637.html 很久之前写过一篇关于 canvas 的文章,是通过 canvas 来实现一个绚丽的动画效果,不管看过没看 ...

  4. PHP的图片处理类(缩放、加图片水印和剪裁)

    <!--test.php文件内容--> <?php //包含这个类image.class.php include "image.class.php"; $img ...

  5. 不错.net图片水印类

    using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Draw ...

  6. [Xcode 实际操作]九、实用进阶-(16)给图片添加水印效果

    目录:[Swift]Xcode实际操作 本文将演示如何截取屏幕画面,并将截取图片,存入系统相册. 在项目文件夹[DemoApp]上点击鼠标右键 ->[New File]创建一个扩展文件-> ...

  7. Python Windows 快捷键自动给剪贴板(复制)图片添加水印

    编写一个能在windows上使用的按下快捷键自动给剪贴板(复制)的图片添加水印的小工具.plyer.PIL.pyinstaller.pynput.win32clipboard库.记录自己踩过的坑,部分 ...

  8. Android 图片添加水印图片或者文字

    给图片添加水印的基本思路都是载入原图,添加文字或者载入水印图片,保存图片这三个部分 添加水印图片: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ...

  9. 分享一下怎么开发一款图片视频类App,秒拍和prisma

    第一步,分解短视频App的功能 我们在秒拍官网看到如此描述: [视频拍摄及导入]支持直接拍摄及导入手机本地的视频 [照片电影]照片专属特效,轻松创作照片电影 [MV特效]10余款全新MV特效,让普通视 ...

随机推荐

  1. spring、spring boot中配置多数据源

    在项目开发的过程中,有时我们有这样的需求,需要去调用别的系统中的数据,那么这个时候系统中就存在多个数据源了,那么我们如何来解决程序在运行的过程中到底是使用的那个数据源呢? 假设我们系统中存在2个数据源 ...

  2. 微信小程序的实现原理

    一.背景 网页开发,渲染线程和脚本是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应的原因,本质就是我们常说的 JS 是单线程的 而在小程序中,选择了 Hybrid 的渲染方式,将视图层和逻 ...

  3. C++STL(set……)

    set 底层实现是用红黑树. set 建立 set<int> s; // 不可重,默认升序 set<int,less> s; // 不可重,升序 set<int,grea ...

  4. 微软认真聆听了开源 .NET 开发社区的炮轰: 通过CLI 支持 Hot Reload 功能

    微软近日激怒了开源.NET社区,起因是它删除了开源.NET的一项旗舰功能,以提升Visual Studio 的吸引力,尤其是针对与Visual Studio颇有渊源的跨平台源代码编辑器Visual S ...

  5. 视频编码GOP

    GOP group of pictures GOP 指的就是两个I帧之间的间隔. 比较说GOP为120,如果是720 p60 的话,那就是2s一次I帧. 在视频编码序列中,主要有三种编码帧:I帧.P帧 ...

  6. x64 InlineHook 黑魔法

    目录 x64 InlineHook 黑魔法 为什么不能用X86 的HOOK方式? 原理:jmp + rip 进行寻址6字节方式跳转 手动InlineHook 临时地址x(找一块空内存) 计算偏移 源地 ...

  7. 欢迎加入XiyouLinuxGroup邮件列表

    一:为什么要使用邮件列表? 与QQ,微信等即时通讯的交流方式相比,使用邮件列表交流有以下好处: 保存性好,易于阅读.它能将一个问题讨论的过程完全保存下来,但是QQ的话,聊天记录很容易就刷没了,再也无法 ...

  8. 使用getopt 解析参数

    getopt被用来解析命令行选项参数. #include <unistd.h> extern char *optarg; //选项的参数指针 extern int optind, //下一 ...

  9. go闭包使用

    1.带参数闭包函数 func main() { //先调用闭包外面的方法传给变量 add_func := add(1, 2) //再调用里面的方法,因为有了i++ 同一个内存地址 在一次编译中i的值会 ...

  10. [python]django的mode设置表结构和serializers序列化数据

    框架使用的库版本 python3.6.5 Django-2.0.6 djangorestframework-3.8.2 mysqlclient-1.3.12 1.项目结构声明,数据库在setting. ...