惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
Netflix TechBlog - Medium
罗磊的独立博客
H
Help Net Security
I
Intezer
G
Google Developers Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
Troy Hunt's Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
U
Unit 42
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
N
News and Events Feed by Topic
J
Java Code Geeks
S
Security Affairs
T
The Blog of Author Tim Ferriss
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
D
Docker
The GitHub Blog
The GitHub Blog
F
Full Disclosure
N
News and Events Feed by Topic
Webroot Blog
Webroot Blog
S
Security @ Cisco Blogs
腾讯CDC
人人都是产品经理
人人都是产品经理
M
MIT News - Artificial intelligence
Blog — PlanetScale
Blog — PlanetScale
T
Threatpost
D
DataBreaches.Net
Recent Announcements
Recent Announcements
博客园 - 三生石上(FineUI控件)
MongoDB | Blog
MongoDB | Blog
博客园 - 【当耐特】
L
LINUX DO - 最新话题
Google Online Security Blog
Google Online Security Blog
S
Schneier on Security
S
Securelist
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Help Net Security
Help Net Security
P
Proofpoint News Feed
Project Zero
Project Zero
S
SegmentFault 最新的问题
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MyScale Blog
MyScale Blog
Google DeepMind News
Google DeepMind News
宝玉的分享
宝玉的分享
Y
Y Combinator Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 叶小钗

青空之蓝

[青空之蓝-2023] - 色彩 | 青空之蓝 [青空之蓝-2022] - 平静 | 青空之蓝 [青空之蓝-2021] - 远望 | 青空之蓝 浅谈垃圾回收 | 青空之蓝 浅谈泛型擦除 | 青空之蓝 浅谈单点登录 | 青空之蓝 使用 Kotlin 编写 Spring 测试 | 青空之蓝 设计模式系列文章 | 青空之蓝 从零实现一个 Java 微框架 - IoC | 青空之蓝 从零实现一个 Java 微框架 - 前言 | 青空之蓝 浅谈 JVM:类加载 | 青空之蓝 浅谈 IO | 青空之蓝 浅谈并发:synchronized & ReentrantLock | 青空之蓝 浅谈并发:CAS & AQS | 青空之蓝 浅谈并发:ThreadLocal | 青空之蓝 浅谈并发:三大特性 | 青空之蓝 浅谈组合注解 & 注解别名 | 青空之蓝 [青空之蓝-2020]-迷茫 | 青空之蓝 Java 系列文章 | 青空之蓝 HTTP 系列文章 | 青空之蓝 浅谈 EatWhatYouKill | 青空之蓝 浅谈可扩展线程池 | 青空之蓝 聊聊写框架 | 青空之蓝 聊聊现状-[2020-09] | 青空之蓝 浅谈并发:锁 | 青空之蓝 浅谈并发:基础 | 青空之蓝 浅谈缓存 | 青空之蓝 无须定义类,Spring 快速注入 Json 参数 | 青空之蓝 浅谈 Proxy 和 Aop | 青空之蓝 从零实现一个 PHP 微框架 - 初始化请求 | 青空之蓝 为 Vue3 添加一个简单的 Store | 青空之蓝 从零实现一个 PHP 微框架 - 服务提供者 | 青空之蓝 WSL2 踩坑记录 | 青空之蓝 浅谈浏览器Event Loop [更新] | 青空之蓝 从零实现一个 PHP 微框架 - Bootstrap 启动加载 | 青空之蓝 从零实现一个 PHP 微框架 - IoC 容器 | 青空之蓝 从零实现一个 PHP 微框架 - PSR & Composer | 青空之蓝 从零实现一个 PHP 微框架 - 前言 | 青空之蓝 MVVM 简单实现 | 青空之蓝 浅谈 DI 和 IoC | 青空之蓝 中间件实现 [PHP] | 青空之蓝 告别 Windows 终端的难看难用,打造好用的 PowerShell | 青空之蓝 VSCode Java输出中文乱码问题解决[更新] | 青空之蓝 浅谈浏览器渲染 | 青空之蓝 Vue-Cli@2 项目迁移日志 | 青空之蓝 Laragon & Scoop 集成踩坑记录 | 青空之蓝 「一行代码」优雅管理 Windows 软件 | 青空之蓝 [青空之蓝-2019]-年度总结 | 青空之蓝 为Vue添加简单的Store | 青空之蓝 为React添加简单的Store | 青空之蓝 为Vuex添加同步Action | 青空之蓝 浅谈B+树 | 青空之蓝 浅谈跳表 | 青空之蓝 浅谈数据库索引 | 青空之蓝 MySQL事务隔离 | 青空之蓝 算法复杂度分析(1) | 青空之蓝 一年来的经验总结 | 青空之蓝 Acrylic - VSCode Extension | 青空之蓝 ace编辑器设置惯性滚动 | 青空之蓝 Java二叉树实现 | 青空之蓝 Java图实现 | 青空之蓝 为apt方式安装的nginx重新编译增加WebDAV | 青空之蓝 XK-Editor - 一个支持富文本和Markdown的编辑器 | 青空之蓝 JS生成列表树 | 青空之蓝 Laravel生成目录树 | 青空之蓝 XK-Note - 集各种神奇功能的云笔记 | 青空之蓝 PHP GD生成验证码 | 青空之蓝 Origami - 简洁轻快的WordPress主题 | 青空之蓝 为WordPress启用WorkBox | 青空之蓝 [青空之蓝-2018]-年度总结 | 青空之蓝 VSCode Java手动导入jar和源码包 | 青空之蓝 Windows IP变化自动发送邮件 | 青空之蓝 C链表实现重制版 | 青空之蓝 C 结构体的定义和使用 | 青空之蓝 图的搜索(遍历) - BFS & DFS | 青空之蓝 Java链表实现 | 青空之蓝 C 快速排序 | 青空之蓝 C 插入排序 | 青空之蓝 C 归并排序 | 青空之蓝 C语言链表实现 | 青空之蓝 VSCode配置Java调试环境[Windows] | 青空之蓝 C 选择排序 | 青空之蓝 C 冒泡排序 | 青空之蓝 VSCode配置PHP调试环境[Windows] | 青空之蓝 VSCode配置C/C++ GDB调试环境[Windows] | 青空之蓝 WordPress友情链接模板 | 青空之蓝 Intel Optane 傲腾内存体验 | 青空之蓝 Mysql双机热备实战 | 青空之蓝 博客一年记录 | 青空之蓝 为WordPress启用Service Worker | 青空之蓝 Bing每日一图API | 青空之蓝 iframe延迟加载 | 青空之蓝 写在2018年高考前 | 青空之蓝 The Fox主题汉化分享 | 青空之蓝 [青空之蓝-2017]-崭新 | 青空之蓝 本博客评论规则 | 青空之蓝 世界,您好! | 青空之蓝
PHP GD图片处理[转换格式-水印-缩略图] | 青空之蓝
Otstar Lin · 2019-02-14 · via 青空之蓝

最近准备弄一个图床,既然是图床就需要能对图片进行一些常用的操作,比如水印,转换格式,生成缩略图等,前几天刚好接触了 PHP 的 GD 库,于是便花了点时间封装了这个简单的图片处理函数。

/**
 * 将图片转换为webp或其他格式,同时可以添加水印
 *
 * @author Otstar Lin
 *
 * @param String   $source            原图片地址
 * @param String   $type              转换后图片格式
 * @param String   $to                转换后图片地址 若为 null 则代表直接输出到浏览器
 * @param Array    $thumbnail_size    缩略图尺寸
 * @param Integer  $thum              要输出到浏览器的图片,当 $to == null 的时候生效, -1 代表使用原尺寸图,其他数字分别代表使用 $thumbnail_size 指定索引的尺寸图
 * @param Boolean  $watermark         是否加水印
 * @param Integer  $watermark_type    水印格式 1:文字 2:图片
 * @param String   $watermark_content 水印内容,若为图片则是水印图片地址
 * @param Integer  $position          水印位置
 * @param Integer  $alpha             水印透明度
 * @param Array    $color             水印内容颜色
 * @param Integer  $font_size         水印文字大小
 * @param String   $font_name         水印字体地址
 */
function image_change($source, $type='webp', $to = null, $thumbnail_size = [], $thum = -1,
                      $watermark = false, $watermark_type = 1, $watermark_content = '', $position = 9,
                      $alpha = 0, $color = [0, 0, 0], $font_size = 14, $font_name = 'Roboto-Medium.ttf')
{
    $image = imagecreatefromstring(file_get_contents($source));
    // 生成水印
    if($watermark) {
        // 获取原图信息
        $image_info = getimagesize($source);
        // 设置颜色
        $content_color = imagecolorallocatealpha($image, $color[0], $color[1], $color[2], $alpha);
        // 载入字体
        putenv('GDFONTPATH=' . realpath('.'));
        $font = $font_name;
        $left = 0;
        $top = 0;
        // 获取水印占据的空间大小
        $watermark_content_info = [];
        if($watermark_type == 1) {
            $temp = imagettfbbox($font_size, 0, $font_name, $watermark_content);
            $watermark_content_info[] = $temp[2] - $temp[0];
            $watermark_content_info[] = $temp[1] - $temp[7];
        } else {
            $temp = getimagesize($watermark_content);
            $watermark_content_info[] = $temp[0];
            $watermark_content_info[] = $temp[1];
        }
        // 对水印进行定位
        switch($position) {
            case 1:
                $left = 20;
                $top = 20;
                break;
            case 2:
                $left = $image_info[0]/2 - $watermark_content_info[0]/2;
                $top = 20;
                break;
            case 3:
                $left = $image_info[0] - $watermark_content_info[0] - 20;
                $top = 20;
                break;
            case 4:
                $left = 20;
                $top = $image_info[1]/2 - $watermark_content_info[1]/2;
                break;
            case 5:
                $left = $image_info[0]/2 - $watermark_content_info[0]/2;
                $top = $image_info[1]/2 - $watermark_content_info[1]/2;
                break;
            case 6:
                $left = $image_info[0] - $watermark_content_info[0] - 20;
                $top = $image_info[1]/2 - $watermark_content_info[1]/2;
                break;
            case 7:
                $left = 20;
                $top = $image_info[1] - $watermark_content_info[1] - 20;
                break;
            case 8:
                $left = $image_info[0]/2 - $watermark_content_info[0]/2;
                $top = $image_info[1] - $watermark_content_info[1] - 20;
                break;
            case 9:
                $left = $image_info[0] - $watermark_content_info[0] - 20;
                $top = $image_info[1] - $watermark_content_info[1] - 20;
                break;
        }
        // 对文字水印和图片水印进行不同的处理
        if($watermark_type == 1) {
            imagettftext($image, $font_size, 0, $left, $font_size + $top, $content_color, $font, $watermark_content);
        } else {
            $watermark_image = imagecreatefromstring(file_get_contents($watermark_content));
            imagecopy($image, $watermark_image, $left, $top, 0, 0, $watermark_content_info[0], $watermark_content_info[1]);
        }
    }
    // 获取图片文件名(去除后缀)
    $image_pathinfo = pathinfo($source);
    $image_name = str_replace('.'.$image_pathinfo['extension'], '', $image_pathinfo['basename']);
    $path = null;
    // 输出原图
    if($to === null) {
        header('Content-type:image/'.$type);
    } else {
        $path = $to.$image_name.'.'.$type;
    }
    if($type == 'jepg') {
        if($thum == -1) imagejpeg($image, $path);
    } else if($type == 'png') {
        if($thum == -1) imagepng($image, $path);
    } else {
        if($thum == -1) imagewebp($image, $path);
    }
    // 输出缩略图
    foreach ($thumbnail_size as $num => $size) {
        $set = true;
        if(!isset($size['height'])) {
            $set = false;
            $size['height'] = $size['width'] * $image_info[1]/$image_info[0];
        }
        $thum_img = imagecreatetruecolor($size['width'], $size['height']);
        imagecopyresampled($thum_img, $image, 0, 0, 0, 0, $size['width'], $size['height'], $image_info[0], $image_info[1]);
        if($to !== null) {
            if($type == 'jepg') {
                imagewebp($thum_img, $to.$image_name.'-'.$size['width'].'.'.$type);
            } else if($type == 'png') {
                imagewebp($thum_img, $to.$image_name.'-'.$size['width'].'.'.$type);
            } else {
                imagewebp($thum_img, $to.$image_name.'-'.$size['width'].'.'.$type);
            }
        } else {
            if($num == $thum) {
                if($type == 'jepg') {
                    imagewebp($thum_img);
                } else if($type == 'png') {
                    imagewebp($thum_img);
                } else {
                    imagewebp($thum_img);
                }
            }
        }
    }
}
// 缩略图的尺寸
$thum = [
    [
        'width' => 200,
    ],
    [
        'width' => 400,
        'height' => 200
    ]
];
image_change('img.png', 'webp', '', $thum, -1, true, 1, 'Otstar Lin', 9, 0);
/**
 * 将图片转换为webp或其他格式,同时可以添加水印
 *
 * @author Otstar Lin
 *
 * @param String   $source            原图片地址
 * @param String   $type              转换后图片格式
 * @param String   $to                转换后图片地址 若为 null 则代表直接输出到浏览器
 * @param Array    $thumbnail_size    缩略图尺寸
 * @param Integer  $thum              要输出到浏览器的图片,当 $to == null 的时候生效, -1 代表使用原尺寸图,其他数字分别代表使用 $thumbnail_size 指定索引的尺寸图
 * @param Boolean  $watermark         是否加水印
 * @param Integer  $watermark_type    水印格式 1:文字 2:图片
 * @param String   $watermark_content 水印内容,若为图片则是水印图片地址
 * @param Integer  $position          水印位置
 * @param Integer  $alpha             水印透明度
 * @param Array    $color             水印内容颜色
 * @param Integer  $font_size         水印文字大小
 * @param String   $font_name         水印字体地址
 */
function image_change($source, $type='webp', $to = null, $thumbnail_size = [], $thum = -1,
                      $watermark = false, $watermark_type = 1, $watermark_content = '', $position = 9,
                      $alpha = 0, $color = [0, 0, 0], $font_size = 14, $font_name = 'Roboto-Medium.ttf')
{
    $image = imagecreatefromstring(file_get_contents($source));
    // 生成水印
    if($watermark) {
        // 获取原图信息
        $image_info = getimagesize($source);
        // 设置颜色
        $content_color = imagecolorallocatealpha($image, $color[0], $color[1], $color[2], $alpha);
        // 载入字体
        putenv('GDFONTPATH=' . realpath('.'));
        $font = $font_name;
        $left = 0;
        $top = 0;
        // 获取水印占据的空间大小
        $watermark_content_info = [];
        if($watermark_type == 1) {
            $temp = imagettfbbox($font_size, 0, $font_name, $watermark_content);
            $watermark_content_info[] = $temp[2] - $temp[0];
            $watermark_content_info[] = $temp[1] - $temp[7];
        } else {
            $temp = getimagesize($watermark_content);
            $watermark_content_info[] = $temp[0];
            $watermark_content_info[] = $temp[1];
        }
        // 对水印进行定位
        switch($position) {
            case 1:
                $left = 20;
                $top = 20;
                break;
            case 2:
                $left = $image_info[0]/2 - $watermark_content_info[0]/2;
                $top = 20;
                break;
            case 3:
                $left = $image_info[0] - $watermark_content_info[0] - 20;
                $top = 20;
                break;
            case 4:
                $left = 20;
                $top = $image_info[1]/2 - $watermark_content_info[1]/2;
                break;
            case 5:
                $left = $image_info[0]/2 - $watermark_content_info[0]/2;
                $top = $image_info[1]/2 - $watermark_content_info[1]/2;
                break;
            case 6:
                $left = $image_info[0] - $watermark_content_info[0] - 20;
                $top = $image_info[1]/2 - $watermark_content_info[1]/2;
                break;
            case 7:
                $left = 20;
                $top = $image_info[1] - $watermark_content_info[1] - 20;
                break;
            case 8:
                $left = $image_info[0]/2 - $watermark_content_info[0]/2;
                $top = $image_info[1] - $watermark_content_info[1] - 20;
                break;
            case 9:
                $left = $image_info[0] - $watermark_content_info[0] - 20;
                $top = $image_info[1] - $watermark_content_info[1] - 20;
                break;
        }
        // 对文字水印和图片水印进行不同的处理
        if($watermark_type == 1) {
            imagettftext($image, $font_size, 0, $left, $font_size + $top, $content_color, $font, $watermark_content);
        } else {
            $watermark_image = imagecreatefromstring(file_get_contents($watermark_content));
            imagecopy($image, $watermark_image, $left, $top, 0, 0, $watermark_content_info[0], $watermark_content_info[1]);
        }
    }
    // 获取图片文件名(去除后缀)
    $image_pathinfo = pathinfo($source);
    $image_name = str_replace('.'.$image_pathinfo['extension'], '', $image_pathinfo['basename']);
    $path = null;
    // 输出原图
    if($to === null) {
        header('Content-type:image/'.$type);
    } else {
        $path = $to.$image_name.'.'.$type;
    }
    if($type == 'jepg') {
        if($thum == -1) imagejpeg($image, $path);
    } else if($type == 'png') {
        if($thum == -1) imagepng($image, $path);
    } else {
        if($thum == -1) imagewebp($image, $path);
    }
    // 输出缩略图
    foreach ($thumbnail_size as $num => $size) {
        $set = true;
        if(!isset($size['height'])) {
            $set = false;
            $size['height'] = $size['width'] * $image_info[1]/$image_info[0];
        }
        $thum_img = imagecreatetruecolor($size['width'], $size['height']);
        imagecopyresampled($thum_img, $image, 0, 0, 0, 0, $size['width'], $size['height'], $image_info[0], $image_info[1]);
        if($to !== null) {
            if($type == 'jepg') {
                imagewebp($thum_img, $to.$image_name.'-'.$size['width'].'.'.$type);
            } else if($type == 'png') {
                imagewebp($thum_img, $to.$image_name.'-'.$size['width'].'.'.$type);
            } else {
                imagewebp($thum_img, $to.$image_name.'-'.$size['width'].'.'.$type);
            }
        } else {
            if($num == $thum) {
                if($type == 'jepg') {
                    imagewebp($thum_img);
                } else if($type == 'png') {
                    imagewebp($thum_img);
                } else {
                    imagewebp($thum_img);
                }
            }
        }
    }
}
// 缩略图的尺寸
$thum = [
    [
        'width' => 200,
    ],
    [
        'width' => 400,
        'height' => 200
    ]
];
image_change('img.png', 'webp', '', $thum, -1, true, 1, 'Otstar Lin', 9, 0);

PHP GD图片处理[转换格式-水印-缩略图]

https://blog.ixk.me/post/php-gd-image-processing
  • 许可协议

    BY-NC-SA

  • 本文作者

    Otstar Lin

  • 发布于

    2019/02/14

转载或引用本文时请遵守许可协议,注明出处、不得用于商业用途!

PHP GD生成验证码Origami - 简洁轻快的WordPress主题