作者 王智

4

/vendor/
/thinkphp/
/composer.lock
/.idea/
\ No newline at end of file
... ...
language: php
php:
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
allow_failures:
- php: 7.0
- php: hhvm
before_script:
- composer self-update
- composer install --prefer-source --no-interaction --dev
script: phpunit --coverage-clover=coverage.xml --configuration=phpunit.xml
after_success:
- bash <(curl -s https://codecov.io/bash)
\ No newline at end of file
... ...
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
... ...
# The ThinkPHP5 Image Package
[![Build Status](https://img.shields.io/travis/top-think/think-image.svg)](https://travis-ci.org/top-think/think-image)
[![Coverage Status](https://img.shields.io/codecov/c/github/top-think/think-image.svg)](https://codecov.io/github/top-think/think-image)
[![Downloads](https://img.shields.io/github/downloads/top-think/think-image/total.svg)](https://github.com/top-think/think-image/releases)
[![Releases](https://img.shields.io/github/release/top-think/think-image.svg)](https://github.com/top-think/think-image/releases/latest)
[![Releases Downloads](https://img.shields.io/github/downloads/top-think/think-image/latest/total.svg)](https://github.com/top-think/think-image/releases/latest)
[![Packagist Status](https://img.shields.io/packagist/v/top-think/think-image.svg)](https://packagist.org/packages/topthink/think-image)
[![Packagist Downloads](https://img.shields.io/packagist/dt/top-think/think-image.svg)](https://packagist.org/packages/topthink/think-image)
## 安装
> composer require topthink/think-image
## 使用
~~~
$image = \think\Image::open('./image.jpg');
或者
$image = \think\Image::open(request()->file('image'));
$image->crop(...)
->thumb(...)
->water(...)
->text(....)
->save(..);
~~~
\ No newline at end of file
... ...
{
"name": "topthink/think-image",
"description": "The ThinkPHP5 Image Package",
"license": "Apache-2.0",
"authors": [
{
"name": "yunwuxin",
"email": "448901948@qq.com"
}
],
"require": {
"ext-gd": "*"
},
"require-dev": {
"topthink/framework": "^5.0",
"phpunit/phpunit": "4.8.*"
},
"config": {
"preferred-install": "dist"
},
"autoload": {
"psr-4": {
"think\\": "src"
}
}
}
... ...
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="tests/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
<testsuites>
<testsuite name="Package Test Suite">
<directory suffix=".php">./tests/</directory>
</testsuite>
</testsuites>
<listeners>
<listener class="JohnKary\PHPUnit\Listener\SpeedTrapListener" />
</listeners>
</phpunit>
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think;
use think\image\Exception as ImageException;
use think\image\gif\Gif;
class Image
{
/* 缩略图相关常量定义 */
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;
/** @var Gif */
protected $gif;
/**
* 图像信息,包括 width, height, type, mime, size
*
* @var array
*/
protected $info;
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 $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;
}
/**
* 返回图像宽度
* @return int 图像宽度
*/
public function width()
{
return $this->info['width'];
}
/**
* 返回图像高度
* @return int 图像高度
*/
public function height()
{
return $this->info['height'];
}
/**
* 返回图像类型
* @return string 图像类型
*/
public function type()
{
return $this->info['type'];
}
/**
* 返回图像MIME类型
* @return string 图像MIME类型
*/
public function mime()
{
return $this->info['mime'];
}
/**
* 返回图像尺寸数组 0 - 图像宽度,1 - 图像高度
* @return array 图像尺寸
*/
public function size()
{
return [$this->info['width'], $this->info['height']];
}
/**
* 旋转图像
* @param int $degrees 顺时针旋转的度数
* @return $this
*/
public function rotate($degrees = 90)
{
do {
$img = imagerotate($this->im, -$degrees, imagecolorallocatealpha($this->im, 0, 0, 0, 127));
imagedestroy($this->im);
$this->im = $img;
} while (!empty($this->gif) && $this->gifNext());
$this->info['width'] = imagesx($this->im);
$this->info['height'] = imagesy($this->im);
return $this;
}
/**
* 翻转图像
* @param integer $direction 翻转轴,X或者Y
* @return $this
*/
public function flip($direction = self::FLIP_X)
{
//原图宽度和高度
$w = $this->info['width'];
$h = $this->info['height'];
do {
$img = imagecreatetruecolor($w, $h);
switch ($direction) {
case self::FLIP_X:
for ($y = 0; $y < $h; $y++) {
imagecopy($img, $this->im, 0, $h - $y - 1, 0, $y, $w, 1);
}
break;
case self::FLIP_Y:
for ($x = 0; $x < $w; $x++) {
imagecopy($img, $this->im, $w - $x - 1, 0, $x, 0, 1, $h);
}
break;
default:
throw new ImageException('不支持的翻转类型');
}
imagedestroy($this->im);
$this->im = $img;
} while (!empty($this->gif) && $this->gifNext());
return $this;
}
/**
* 裁剪图像
*
* @param integer $w 裁剪区域宽度
* @param integer $h 裁剪区域高度
* @param integer $x 裁剪区域x坐标
* @param integer $y 裁剪区域y坐标
* @param integer $width 图像保存宽度
* @param integer $height 图像保存高度
*
* @return $this
*/
public function crop($w, $h, $x = 0, $y = 0, $width = null, $height = null)
{
//设置保存尺寸
empty($width) && $width = $w;
empty($height) && $height = $h;
do {
//创建新图像
$img = imagecreatetruecolor($width, $height);
// 调整默认颜色
$color = imagecolorallocate($img, 255, 255, 255);
imagefill($img, 0, 0, $color);
//裁剪
imagecopyresampled($img, $this->im, 0, 0, $x, $y, $width, $height, $w, $h);
imagedestroy($this->im); //销毁原图
//设置新图像
$this->im = $img;
} while (!empty($this->gif) && $this->gifNext());
$this->info['width'] = (int) $width;
$this->info['height'] = (int) $height;
return $this;
}
/**
* 生成缩略图
*
* @param integer $width 缩略图最大宽度
* @param integer $height 缩略图最大高度
* @param int $type 缩略图裁剪类型
*
* @return $this
*/
public function thumb($width, $height, $type = self::THUMB_SCALING)
{
//原图宽度和高度
$w = $this->info['width'];
$h = $this->info['height'];
/* 计算缩略图生成的必要参数 */
switch ($type) {
/* 等比例缩放 */
case self::THUMB_SCALING:
//原图尺寸小于缩略图尺寸则不进行缩略
if ($w < $width && $h < $height) {
return $this;
}
//计算缩放比例
$scale = min($width / $w, $height / $h);
//设置缩略图的坐标及宽度和高度
$x = $y = 0;
$width = $w * $scale;
$height = $h * $scale;
break;
/* 居中裁剪 */
case self::THUMB_CENTER:
//计算缩放比例
$scale = max($width / $w, $height / $h);
//设置缩略图的坐标及宽度和高度
$w = $width / $scale;
$h = $height / $scale;
$x = ($this->info['width'] - $w) / 2;
$y = ($this->info['height'] - $h) / 2;
break;
/* 左上角裁剪 */
case self::THUMB_NORTHWEST:
//计算缩放比例
$scale = max($width / $w, $height / $h);
//设置缩略图的坐标及宽度和高度
$x = $y = 0;
$w = $width / $scale;
$h = $height / $scale;
break;
/* 右下角裁剪 */
case self::THUMB_SOUTHEAST:
//计算缩放比例
$scale = max($width / $w, $height / $h);
//设置缩略图的坐标及宽度和高度
$w = $width / $scale;
$h = $height / $scale;
$x = $this->info['width'] - $w;
$y = $this->info['height'] - $h;
break;
/* 填充 */
case self::THUMB_FILLED:
//计算缩放比例
if ($w < $width && $h < $height) {
$scale = 1;
} else {
$scale = min($width / $w, $height / $h);
}
//设置缩略图的坐标及宽度和高度
$neww = $w * $scale;
$newh = $h * $scale;
$x = $this->info['width'] - $w;
$y = $this->info['height'] - $h;
$posx = ($width - $w * $scale) / 2;
$posy = ($height - $h * $scale) / 2;
do {
//创建新图像
$img = imagecreatetruecolor($width, $height);
// 调整默认颜色
$color = imagecolorallocate($img, 255, 255, 255);
imagefill($img, 0, 0, $color);
//裁剪
imagecopyresampled($img, $this->im, $posx, $posy, $x, $y, $neww, $newh, $w, $h);
imagedestroy($this->im); //销毁原图
$this->im = $img;
} while (!empty($this->gif) && $this->gifNext());
$this->info['width'] = (int) $width;
$this->info['height'] = (int) $height;
return $this;
/* 固定 */
case self::THUMB_FIXED:
$x = $y = 0;
break;
default:
throw new ImageException('不支持的缩略图裁剪类型');
}
/* 裁剪图像 */
return $this->crop($w, $h, $x, $y, $width, $height);
}
/**
* 添加水印
*
* @param string $source 水印图片路径
* @param int $locate 水印位置
* @param int $alpha 透明度
* @return $this
*/
public function water($source, $locate = self::WATER_SOUTHEAST, $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, 255, 255, 255);
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 $text 添加的文字
* @param string $font 字体路径
* @param integer $size 字号
* @param string $color 文字颜色
* @param int $locate 文字写入位置
* @param integer $offset 文字相对当前位置的偏移量
* @param integer $angle 文字倾斜角度
*
* @return $this
* @throws ImageException
*/
public function text($text, $font, $size, $color = '#00000000',
$locate = self::WATER_SOUTHEAST, $offset = 0, $angle = 0) {
if (!is_file($font)) {
throw new ImageException("不存在的字体文件:{$font}");
}
//获取文字信息
$info = imagettfbbox($size, $angle, $font, $text);
$minx = min($info[0], $info[2], $info[4], $info[6]);
$maxx = max($info[0], $info[2], $info[4], $info[6]);
$miny = min($info[1], $info[3], $info[5], $info[7]);
$maxy = max($info[1], $info[3], $info[5], $info[7]);
/* 计算文字初始坐标和尺寸 */
$x = $minx;
$y = abs($miny);
$w = $maxx - $minx;
$h = $maxy - $miny;
/* 设定文字位置 */
switch ($locate) {
/* 右下角文字 */
case self::WATER_SOUTHEAST:
$x += $this->info['width'] - $w;
$y += $this->info['height'] - $h;
break;
/* 左下角文字 */
case self::WATER_SOUTHWEST:
$y += $this->info['height'] - $h;
break;
/* 左上角文字 */
case self::WATER_NORTHWEST:
// 起始坐标即为左上角坐标,无需调整
break;
/* 右上角文字 */
case self::WATER_NORTHEAST:
$x += $this->info['width'] - $w;
break;
/* 居中文字 */
case self::WATER_CENTER:
$x += ($this->info['width'] - $w) / 2;
$y += ($this->info['height'] - $h) / 2;
break;
/* 下居中文字 */
case self::WATER_SOUTH:
$x += ($this->info['width'] - $w) / 2;
$y += $this->info['height'] - $h;
break;
/* 右居中文字 */
case self::WATER_EAST:
$x += $this->info['width'] - $w;
$y += ($this->info['height'] - $h) / 2;
break;
/* 上居中文字 */
case self::WATER_NORTH:
$x += ($this->info['width'] - $w) / 2;
break;
/* 左居中文字 */
case self::WATER_WEST:
$y += ($this->info['height'] - $h) / 2;
break;
default:
/* 自定义文字坐标 */
if (is_array($locate)) {
list($posx, $posy) = $locate;
$x += $posx;
$y += $posy;
} else {
throw new ImageException('不支持的文字位置类型');
}
}
/* 设置偏移量 */
if (is_array($offset)) {
$offset = array_map('intval', $offset);
list($ox, $oy) = $offset;
} else {
$offset = intval($offset);
$ox = $oy = $offset;
}
/* 设置颜色 */
if (is_string($color) && 0 === strpos($color, '#')) {
$color = str_split(substr($color, 1), 2);
$color = array_map('hexdec', $color);
if (empty($color[3]) || $color[3] > 127) {
$color[3] = 0;
}
} elseif (!is_array($color)) {
throw new ImageException('错误的颜色值');
}
do {
/* 写入文字 */
$col = imagecolorallocatealpha($this->im, $color[0], $color[1], $color[2], $color[3]);
imagettftext($this->im, $size, $angle, $x + $ox, $y + $oy, $col, $font, $text);
} while (!empty($this->gif) && $this->gifNext());
return $this;
}
/**
* 切换到GIF的下一帧并保存当前帧
*/
protected function gifNext()
{
ob_start();
ob_implicit_flush(0);
imagegif($this->im);
$img = ob_get_clean();
$this->gif->image($img);
$next = $this->gif->nextImage();
if ($next) {
imagedestroy($this->im);
$this->im = imagecreatefromstring($next);
return $next;
} else {
imagedestroy($this->im);
$this->im = imagecreatefromstring($this->gif->image());
return false;
}
}
/**
* 析构方法,用于销毁图像资源
*/
public function __destruct()
{
empty($this->im) || imagedestroy($this->im);
}
}
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\image;
class Exception extends \RuntimeException
{
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\image\gif;
class Decoder
{
public $GIF_buffer = [];
public $GIF_arrays = [];
public $GIF_delays = [];
public $GIF_stream = "";
public $GIF_string = "";
public $GIF_bfseek = 0;
public $GIF_screen = [];
public $GIF_global = [];
public $GIF_sorted;
public $GIF_colorS;
public $GIF_colorC;
public $GIF_colorF;
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFDecoder ( $GIF_pointer )
::
*/
public function __construct($GIF_pointer)
{
$this->GIF_stream = $GIF_pointer;
$this->getByte(6); // GIF89a
$this->getByte(7); // Logical Screen Descriptor
$this->GIF_screen = $this->GIF_buffer;
$this->GIF_colorF = $this->GIF_buffer[4] & 0x80 ? 1 : 0;
$this->GIF_sorted = $this->GIF_buffer[4] & 0x08 ? 1 : 0;
$this->GIF_colorC = $this->GIF_buffer[4] & 0x07;
$this->GIF_colorS = 2 << $this->GIF_colorC;
if (1 == $this->GIF_colorF) {
$this->getByte(3 * $this->GIF_colorS);
$this->GIF_global = $this->GIF_buffer;
}
for ($cycle = 1; $cycle;) {
if ($this->getByte(1)) {
switch ($this->GIF_buffer[0]) {
case 0x21:
$this->readExtensions();
break;
case 0x2C:
$this->readDescriptor();
break;
case 0x3B:
$cycle = 0;
break;
}
} else {
$cycle = 0;
}
}
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFReadExtension ( )
::
*/
public function readExtensions()
{
$this->getByte(1);
for (; ;) {
$this->getByte(1);
if (($u = $this->GIF_buffer[0]) == 0x00) {
break;
}
$this->getByte($u);
/*
* 07.05.2007.
* Implemented a new line for a new function
* to determine the originaly delays between
* frames.
*
*/
if (4 == $u) {
$this->GIF_delays[] = ($this->GIF_buffer[1] | $this->GIF_buffer[2] << 8);
}
}
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFReadExtension ( )
::
*/
public function readDescriptor()
{
$this->getByte(9);
$GIF_screen = $this->GIF_buffer;
$GIF_colorF = $this->GIF_buffer[8] & 0x80 ? 1 : 0;
if ($GIF_colorF) {
$GIF_code = $this->GIF_buffer[8] & 0x07;
$GIF_sort = $this->GIF_buffer[8] & 0x20 ? 1 : 0;
} else {
$GIF_code = $this->GIF_colorC;
$GIF_sort = $this->GIF_sorted;
}
$GIF_size = 2 << $GIF_code;
$this->GIF_screen[4] &= 0x70;
$this->GIF_screen[4] |= 0x80;
$this->GIF_screen[4] |= $GIF_code;
if ($GIF_sort) {
$this->GIF_screen[4] |= 0x08;
}
$this->GIF_string = "GIF87a";
$this->putByte($this->GIF_screen);
if (1 == $GIF_colorF) {
$this->getByte(3 * $GIF_size);
$this->putByte($this->GIF_buffer);
} else {
$this->putByte($this->GIF_global);
}
$this->GIF_string .= chr(0x2C);
$GIF_screen[8] &= 0x40;
$this->putByte($GIF_screen);
$this->getByte(1);
$this->putByte($this->GIF_buffer);
for (; ;) {
$this->getByte(1);
$this->putByte($this->GIF_buffer);
if (($u = $this->GIF_buffer[0]) == 0x00) {
break;
}
$this->getByte($u);
$this->putByte($this->GIF_buffer);
}
$this->GIF_string .= chr(0x3B);
/*
Add frames into $GIF_stream array...
*/
$this->GIF_arrays[] = $this->GIF_string;
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFGetByte ( $len )
::
*/
public function getByte($len)
{
$this->GIF_buffer = [];
for ($i = 0; $i < $len; $i++) {
if ($this->GIF_bfseek > strlen($this->GIF_stream)) {
return 0;
}
$this->GIF_buffer[] = ord($this->GIF_stream{$this->GIF_bfseek++});
}
return 1;
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFPutByte ( $bytes )
::
*/
public function putByte($bytes)
{
for ($i = 0; $i < count($bytes); $i++) {
$this->GIF_string .= chr($bytes[$i]);
}
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: PUBLIC FUNCTIONS
::
::
:: GIFGetFrames ( )
::
*/
public function getFrames()
{
return ($this->GIF_arrays);
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFGetDelays ( )
::
*/
public function getDelays()
{
return ($this->GIF_delays);
}
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\image\gif;
class Encoder
{
public $GIF = "GIF89a"; /* GIF header 6 bytes */
public $VER = "GIFEncoder V2.05"; /* Encoder version */
public $BUF = [];
public $LOP = 0;
public $DIS = 2;
public $COL = -1;
public $IMG = -1;
public $ERR = [
'ERR00' => "Does not supported function for only one image!",
'ERR01' => "Source is not a GIF image!",
'ERR02' => "Unintelligible flag ",
'ERR03' => "Does not make animation from animated GIF source",
];
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFEncoder...
::
*/
public function __construct(
$GIF_src, $GIF_dly, $GIF_lop, $GIF_dis,
$GIF_red, $GIF_grn, $GIF_blu, $GIF_mod
)
{
if (!is_array($GIF_src)) {
printf("%s: %s", $this->VER, $this->ERR['ERR00']);
exit(0);
}
$this->LOP = ($GIF_lop > -1) ? $GIF_lop : 0;
$this->DIS = ($GIF_dis > -1) ? (($GIF_dis < 3) ? $GIF_dis : 3) : 2;
$this->COL = ($GIF_red > -1 && $GIF_grn > -1 && $GIF_blu > -1) ?
($GIF_red | ($GIF_grn << 8) | ($GIF_blu << 16)) : -1;
for ($i = 0; $i < count($GIF_src); $i++) {
if (strtolower($GIF_mod) == "url") {
$this->BUF[] = fread(fopen($GIF_src[$i], "rb"), filesize($GIF_src[$i]));
} else if (strtolower($GIF_mod) == "bin") {
$this->BUF[] = $GIF_src[$i];
} else {
printf("%s: %s ( %s )!", $this->VER, $this->ERR['ERR02'], $GIF_mod);
exit(0);
}
if (substr($this->BUF[$i], 0, 6) != "GIF87a" && substr($this->BUF[$i], 0, 6) != "GIF89a") {
printf("%s: %d %s", $this->VER, $i, $this->ERR['ERR01']);
exit(0);
}
for ($j = (13 + 3 * (2 << (ord($this->BUF[$i]{10}) & 0x07))), $k = true; $k; $j++) {
switch ($this->BUF[$i]{$j}) {
case "!":
if ((substr($this->BUF[$i], ($j + 3), 8)) == "NETSCAPE") {
printf("%s: %s ( %s source )!", $this->VER, $this->ERR['ERR03'], ($i + 1));
exit(0);
}
break;
case ";":
$k = false;
break;
}
}
}
$this->addHeader();
for ($i = 0; $i < count($this->BUF); $i++) {
$this->addFrames($i, $GIF_dly[$i]);
}
$this->addFooter();
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFAddHeader...
::
*/
public function addHeader()
{
if (ord($this->BUF[0]{10}) & 0x80) {
$cmap = 3 * (2 << (ord($this->BUF[0]{10}) & 0x07));
$this->GIF .= substr($this->BUF[0], 6, 7);
$this->GIF .= substr($this->BUF[0], 13, $cmap);
$this->GIF .= "!\377\13NETSCAPE2.0\3\1" . $this->word($this->LOP) . "\0";
}
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFAddFrames...
::
*/
public function addFrames($i, $d)
{
$Locals_img = '';
$Locals_str = 13 + 3 * (2 << (ord($this->BUF[$i]{10}) & 0x07));
$Locals_end = strlen($this->BUF[$i]) - $Locals_str - 1;
$Locals_tmp = substr($this->BUF[$i], $Locals_str, $Locals_end);
$Global_len = 2 << (ord($this->BUF[0]{10}) & 0x07);
$Locals_len = 2 << (ord($this->BUF[$i]{10}) & 0x07);
$Global_rgb = substr($this->BUF[0], 13,
3 * (2 << (ord($this->BUF[0]{10}) & 0x07)));
$Locals_rgb = substr($this->BUF[$i], 13,
3 * (2 << (ord($this->BUF[$i]{10}) & 0x07)));
$Locals_ext = "!\xF9\x04" . chr(($this->DIS << 2) + 0) .
chr(($d >> 0) & 0xFF) . chr(($d >> 8) & 0xFF) . "\x0\x0";
if ($this->COL > -1 && ord($this->BUF[$i]{10}) & 0x80) {
for ($j = 0; $j < (2 << (ord($this->BUF[$i]{10}) & 0x07)); $j++) {
if (
ord($Locals_rgb{3 * $j + 0}) == (($this->COL >> 16) & 0xFF) &&
ord($Locals_rgb{3 * $j + 1}) == (($this->COL >> 8) & 0xFF) &&
ord($Locals_rgb{3 * $j + 2}) == (($this->COL >> 0) & 0xFF)
) {
$Locals_ext = "!\xF9\x04" . chr(($this->DIS << 2) + 1) .
chr(($d >> 0) & 0xFF) . chr(($d >> 8) & 0xFF) . chr($j) . "\x0";
break;
}
}
}
switch ($Locals_tmp{0}) {
case "!":
/**
* @var string $Locals_img ;
*/
$Locals_img = substr($Locals_tmp, 8, 10);
$Locals_tmp = substr($Locals_tmp, 18, strlen($Locals_tmp) - 18);
break;
case ",":
$Locals_img = substr($Locals_tmp, 0, 10);
$Locals_tmp = substr($Locals_tmp, 10, strlen($Locals_tmp) - 10);
break;
}
if (ord($this->BUF[$i]{10}) & 0x80 && $this->IMG > -1) {
if ($Global_len == $Locals_len) {
if ($this->blockCompare($Global_rgb, $Locals_rgb, $Global_len)) {
$this->GIF .= ($Locals_ext . $Locals_img . $Locals_tmp);
} else {
$byte = ord($Locals_img{9});
$byte |= 0x80;
$byte &= 0xF8;
$byte |= (ord($this->BUF[0]{10}) & 0x07);
$Locals_img{9} = chr($byte);
$this->GIF .= ($Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp);
}
} else {
$byte = ord($Locals_img{9});
$byte |= 0x80;
$byte &= 0xF8;
$byte |= (ord($this->BUF[$i]{10}) & 0x07);
$Locals_img{9} = chr($byte);
$this->GIF .= ($Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp);
}
} else {
$this->GIF .= ($Locals_ext . $Locals_img . $Locals_tmp);
}
$this->IMG = 1;
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFAddFooter...
::
*/
public function addFooter()
{
$this->GIF .= ";";
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFBlockCompare...
::
*/
public function blockCompare($GlobalBlock, $LocalBlock, $Len)
{
for ($i = 0; $i < $Len; $i++) {
if (
$GlobalBlock{3 * $i + 0} != $LocalBlock{3 * $i + 0} ||
$GlobalBlock{3 * $i + 1} != $LocalBlock{3 * $i + 1} ||
$GlobalBlock{3 * $i + 2} != $LocalBlock{3 * $i + 2}
) {
return (0);
}
}
return (1);
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFWord...
::
*/
public function word($int)
{
return (chr($int & 0xFF) . chr(($int >> 8) & 0xFF));
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GetAnimation...
::
*/
public function getAnimation()
{
return ($this->GIF);
}
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\image\gif;
class Gif
{
/**
* GIF帧列表
*
* @var array
*/
private $frames = [];
/**
* 每帧等待时间列表
*
* @var array
*/
private $delays = [];
/**
* 构造方法,用于解码GIF图片
*
* @param string $src GIF图片数据
* @param string $mod 图片数据类型
* @throws \Exception
*/
public function __construct($src = null, $mod = 'url')
{
if (!is_null($src)) {
if ('url' == $mod && is_file($src)) {
$src = file_get_contents($src);
}
/* 解码GIF图片 */
try {
$de = new Decoder($src);
$this->frames = $de->getFrames();
$this->delays = $de->getDelays();
} catch (\Exception $e) {
throw new \Exception("解码GIF图片出错");
}
}
}
/**
* 设置或获取当前帧的数据
*
* @param string $stream 二进制数据流
* @return mixed 获取到的数据
*/
public function image($stream = null)
{
if (is_null($stream)) {
$current = current($this->frames);
return false === $current ? reset($this->frames) : $current;
}
$this->frames[key($this->frames)] = $stream;
}
/**
* 将当前帧移动到下一帧
*
* @return string 当前帧数据
*/
public function nextImage()
{
return next($this->frames);
}
/**
* 编码并保存当前GIF图片
*
* @param string $pathname 图片名称
*/
public function save($pathname)
{
$gif = new Encoder($this->frames, $this->delays, 0, 2, 0, 0, 0, 'bin');
file_put_contents($pathname, $gif->getAnimation());
}
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace tests;
use think\Image;
class CropTest extends TestCase
{
public function testJpeg()
{
$pathname = TEST_PATH . 'tmp/crop.jpg';
$image = Image::open($this->getJpeg());
$image->crop(200, 200, 100, 100, 300, 300)->save($pathname);
$this->assertEquals(300, $image->width());
$this->assertEquals(300, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
public function testPng()
{
$pathname = TEST_PATH . 'tmp/crop.png';
$image = Image::open($this->getPng());
$image->crop(200, 200, 100, 100, 300, 300)->save($pathname);
$this->assertEquals(300, $image->width());
$this->assertEquals(300, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
public function testGif()
{
$pathname = TEST_PATH . 'tmp/crop.gif';
$image = Image::open($this->getGif());
$image->crop(200, 200, 100, 100, 300, 300)->save($pathname);
$this->assertEquals(300, $image->width());
$this->assertEquals(300, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace tests;
use think\Image;
class FlipTest extends TestCase
{
public function testJpeg()
{
$pathname = TEST_PATH . 'tmp/flip.jpg';
$image = Image::open($this->getJpeg());
$image->flip()->save($pathname);
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
public function testGif()
{
$pathname = TEST_PATH . 'tmp/flip.gif';
$image = Image::open($this->getGif());
$image->flip(Image::FLIP_Y)->save($pathname);
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace tests;
use think\Image;
class InfoTest extends TestCase
{
public function testOpen()
{
$this->setExpectedException("\\think\\image\\Exception");
Image::open('');
}
public function testIllegal()
{
$this->setExpectedException("\\think\\image\\Exception", 'Illegal image file');
Image::open(TEST_PATH . 'images/test.bmp');
}
public function testJpeg()
{
$image = Image::open($this->getJpeg());
$this->assertEquals(800, $image->width());
$this->assertEquals(600, $image->height());
$this->assertEquals('jpeg', $image->type());
$this->assertEquals('image/jpeg', $image->mime());
$this->assertEquals([800, 600], $image->size());
}
public function testPng()
{
$image = Image::open($this->getPng());
$this->assertEquals(800, $image->width());
$this->assertEquals(600, $image->height());
$this->assertEquals('png', $image->type());
$this->assertEquals('image/png', $image->mime());
$this->assertEquals([800, 600], $image->size());
}
public function testGif()
{
$image = Image::open($this->getGif());
$this->assertEquals(380, $image->width());
$this->assertEquals(216, $image->height());
$this->assertEquals('gif', $image->type());
$this->assertEquals('image/gif', $image->mime());
$this->assertEquals([380, 216], $image->size());
}
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace tests;
use think\Image;
class RotateTest extends TestCase
{
public function testJpeg()
{
$pathname = TEST_PATH . 'tmp/rotate.jpg';
$image = Image::open($this->getJpeg());
$image->rotate(90)->save($pathname);
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
public function testGif()
{
$pathname = TEST_PATH . 'tmp/rotate.gif';
$image = Image::open($this->getGif());
$image->rotate(90)->save($pathname);
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace tests;
use think\File;
abstract class TestCase extends \PHPUnit_Framework_TestCase
{
protected function getJpeg()
{
return new File(TEST_PATH . 'images/test.jpg');
}
protected function getPng()
{
return new File(TEST_PATH . 'images/test.png');
}
protected function getGif()
{
return new File(TEST_PATH . 'images/test.gif');
}
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace tests;
use think\Image;
class TextTest extends TestCase
{
public function testJpeg()
{
$pathname = TEST_PATH . 'tmp/text.jpg';
$image = Image::open($this->getJpeg());
$image->text('test', TEST_PATH . 'images/test.ttf', 12)->save($pathname);
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
public function testPng()
{
$pathname = TEST_PATH . 'tmp/text.png';
$image = Image::open($this->getPng());
$image->text('test', TEST_PATH . 'images/test.ttf', 12)->save($pathname);
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
public function testGif()
{
$pathname = TEST_PATH . 'tmp/text.gif';
$image = Image::open($this->getGif());
$image->text('test', TEST_PATH . 'images/test.ttf', 12)->save($pathname);
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace tests;
use think\Image;
class ThumbTest extends TestCase
{
public function testJpeg()
{
$pathname = TEST_PATH . 'tmp/thumb.jpg';
//1
$image = Image::open($this->getJpeg());
$image->thumb(200, 200, Image::THUMB_CENTER)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//2
$image = Image::open($this->getJpeg());
$image->thumb(200, 200, Image::THUMB_SCALING)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(150, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//3
$image = Image::open($this->getJpeg());
$image->thumb(200, 200, Image::THUMB_FILLED)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//4
$image = Image::open($this->getJpeg());
$image->thumb(200, 200, Image::THUMB_NORTHWEST)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//5
$image = Image::open($this->getJpeg());
$image->thumb(200, 200, Image::THUMB_SOUTHEAST)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//6
$image = Image::open($this->getJpeg());
$image->thumb(200, 200, Image::THUMB_FIXED)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
public function testPng()
{
$pathname = TEST_PATH . 'tmp/thumb.png';
//1
$image = Image::open($this->getPng());
$image->thumb(200, 200, Image::THUMB_CENTER)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//2
$image = Image::open($this->getPng());
$image->thumb(200, 200, Image::THUMB_SCALING)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(150, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//3
$image = Image::open($this->getPng());
$image->thumb(200, 200, Image::THUMB_FILLED)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//4
$image = Image::open($this->getPng());
$image->thumb(200, 200, Image::THUMB_NORTHWEST)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//5
$image = Image::open($this->getPng());
$image->thumb(200, 200, Image::THUMB_SOUTHEAST)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//6
$image = Image::open($this->getPng());
$image->thumb(200, 200, Image::THUMB_FIXED)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
public function testGif()
{
$pathname = TEST_PATH . 'tmp/thumb.gif';
//1
$image = Image::open($this->getGif());
$image->thumb(200, 200, Image::THUMB_CENTER)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//2
$image = Image::open($this->getGif());
$image->thumb(200, 200, Image::THUMB_SCALING)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(113, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//3
$image = Image::open($this->getGif());
$image->thumb(200, 200, Image::THUMB_FILLED)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//4
$image = Image::open($this->getGif());
$image->thumb(200, 200, Image::THUMB_NORTHWEST)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//5
$image = Image::open($this->getGif());
$image->thumb(200, 200, Image::THUMB_SOUTHEAST)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
//6
$image = Image::open($this->getGif());
$image->thumb(200, 200, Image::THUMB_FIXED)->save($pathname);
$this->assertEquals(200, $image->width());
$this->assertEquals(200, $image->height());
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace tests;
use think\Image;
class WaterTest extends TestCase
{
public function testJpeg()
{
$pathname = TEST_PATH . 'tmp/water.jpg';
$image = Image::open($this->getJpeg());
$image->water(TEST_PATH . 'images/test.gif')->save($pathname);
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
public function testPng()
{
$pathname = TEST_PATH . 'tmp/water.png';
$image = Image::open($this->getPng());
$image->water(TEST_PATH . 'images/test.gif')->save($pathname);
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
public function testGif()
{
$pathname = TEST_PATH . 'tmp/water.gif';
$image = Image::open($this->getGif());
$image->water(TEST_PATH . 'images/test.jpg')->save($pathname);
$file = new \SplFileInfo($pathname);
$this->assertTrue($file->isFile());
@unlink($pathname);
}
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
define('TEST_PATH', __DIR__ . '/');
// 加载框架基础文件
require __DIR__ . '/../thinkphp/base.php';
\think\Loader::addNamespace('tests', TEST_PATH);
\think\Loader::addNamespace('think', __DIR__ . '/../src/');
\ No newline at end of file
... ...
*
!.gitignore
\ No newline at end of file
... ...