loops / gdimage
辅助GD库导入、转换、导出图像。此库提供:GIF支持、JPEG支持、PNG24支持、PNG8支持、动画GIF支持、APNG支持、HTTP支持、数据URI支持、调色板颜色增强(特别是GD透明颜色泄漏),调整大小(裁剪、适应、填充),颜色过滤
Requires
- php: >=5.3
- ext-gd: *
Suggests
- ext-fileinfo: Provide better MIME type detection.
This package is auto-updated.
Last update: 2024-09-09 13:27:56 UTC
README
要求
至少PHP 5.3,GD库是必需的。
如何使用它
自动加载
如果您没有composer,请调用bootstrap
:::php
require $path_to_library.'/bootstrap.inc.php';
此库使用PSR-0与一个命名空间,并可能永远不会转到PSR-4。
图像格式
此库支持GIF、JPEG、PNG24、PNG8、AGIF(动画GIF)和APNG。
导入
基本用法
您可以从许多来源导入图像:文件、二进制、base64、数据URI...
它们都通过 \GDImage\Factory::import() 方法处理。
:::php
$image = \GDImage\Factory::import( $stuff );
绕过
为了优化性能,您可能想绕过工厂层。在这种情况下,您可以使用任何 \GDImage\Image_Interface 的相应方法绕过文件或二进制导入。
:::php
// import file as GIF
$image = new \GDImage\Image_Gif();
$image->fromFile( $filepath );
// import binary as PNG
$image = new \GDImage\Image_Png();
$image->fromBinary( $filepath );
在导入时绕过工厂层,您必须知道图像的MIME类型。
导出
基本用法
您可以将图像导出到多种格式:文件、二进制数据、base64数据、数据URI方案...
它们都通过 \GDImage\Factory::export() 方法处理。
:::php
// export to file
// on file export, if no extension is specified on the filepath, it will be
// automatically added
$final_filepath = \GDImage\Factory::export( $image , $filepath );
// export to data URI
$data_uri = \GDImage\Factory::export( $image , 'data' );
// export to base 64
$data_uri = \GDImage\Factory::export( $image , 'base64' );
// export to binary
$data_uri = \GDImage\Factory::export( $image , 'binary' );
// export to output
\GDImage\Factory::export( $image , 'output' );
强制MIME类型
如果您希望将图像强制导出到预期的MIME类型,可以这样做。
:::php
// export to file with PNG MIME Type
$final_filepath = \GDImage\Factory::export( $image , $filepath , 'image/png' );
导出参数
如果您需要额外的导出参数,第二个参数可以是一个数组。
:::php
// export to data URI without base 64 encoding and MIME Type
$data_uri = \GDImage\Factory::export( $image , array(
'driver' => 'DataUri' ,
'base64' => false ,
'mimetype' => false ,
) );
未命名的参数将传递到最终的GD函数(如 imagejpeg()、imagepng()...),但您必须知道将使用哪个函数。
:::php
// export to file with JPEG MIME Type and 75 quality
$final_filepath = \GDImage\Factory::export( $image , array(
'driver' => 'File' ,
'file' => $filepath ,
95 ,
) , 'image/jpeg' );
// export to file with PNG MIME Type, 8 compression level and all PNG filters
$final_filepath = \GDImage\Factory::export( $image , array(
'driver' => 'File' ,
'file' => $filepath ,
8 ,
PNG_ALL_FILTERS ,
) , 'image/png' );
绕过
为了优化性能,您可能想绕过工厂层。在这种情况下,您可以使用任何 \GDImage\Image_Interface 的相应方法绕过文件或二进制导出。
:::php
// export to file
$success = $image->toFile( $filepath );
// export to binary
$binary = $image->toBinary();
转换
理念
转换是在图像实例上应用以修改其资源或动画图像的资源。
通过分离图像操作和图像资源,相同的转换可以安全地应用于任何图像。
:::php
$image = \GDImage\Factory::import( $import_filepath );
$transform = new \GDImage\Transform_GaussianBlur();
$image->apply( $transform );
$final_filepath = \GDImage\Factory::export( $image , $export_filepath );
主要转换
以下是主要转换列表
\GDImage\Transform_Resize_Fit:将图像缩放到最大尺寸,使其宽度和高度都适合区域。最终的宽度和高度可能小于预期,但不一定都小于预期。
:::php
$image = \GDImage\Factory::import( $import_filepath );
$transform = new \GDImage\Transform_Resize_Fit( 300 , 300 );
$image->apply( $transform );
$final_filepath = \GDImage\Factory::export( $image , $export_filepath );
如果您只想使图像适应预期的宽度,可以这样操作
:::php
$image = \GDImage\Factory::import( $import_filepath );
$transform = new \GDImage\Transform_Resize_Fit( 300 , \PHP_INT_MAX );
$image->apply( $transform );
$final_filepath = \GDImage\Factory::export( $image , $export_filepath );
\GDImage\Transform_Resize_Crop:将图像缩放到最大尺寸,使其完全覆盖区域。图像的一些部分将被裁剪,最终的宽度和高度将与预期完全一致。
:::php
$image = \GDImage\Factory::import( $import_filepath );
$transform = new \GDImage\Transform_Resize_Crop( 300 , 300 );
$image->apply( $transform );
$final_filepath = \GDImage\Factory::export( $image , $export_filepath );
\GDImage\Transform_Resize_FitNFill:将图像缩放到最大尺寸,使其宽度和高度都适合区域。空白区域将被透明颜色填充,以确保最终的宽度和高度与预期完全一致。
:::php
$image = \GDImage\Factory::import( $import_filepath );
$transform = new \GDImage\Transform_Resize_FitNFill( 300 , 300 );
$image->apply( $transform );
$final_filepath = \GDImage\Factory::export( $image , $export_filepath );
您可以指定填充的颜色
:::php
$image = \GDImage\Factory::import( $import_filepath );
// fill with white
$transform = new \GDImage\Transform_Resize_FitNFill( 300 , 300 , 'FFFFFF' );
$image->apply( $transform );
$final_filepath = \GDImage\Factory::export( $image , $export_filepath );
还有很多其他的转换,所以请不要犹豫去查看测试案例或 Transform 文件夹。
多个转换
您可以将多个转换组合成一个。
:::php
$image = \GDImage\Factory::import( $import_filepath );
$transform = new \GDImage\Transform_Multiple(
new \GDImage\Transform_Grayscale() ,
new \GDImage\Transform_Negate()
);
$image->apply( $transform );
$final_filepath = \GDImage\Factory::export( $image , $export_filepath );
注册转换
您可以注册一个转换,甚至是多个转换,以便以后使用。通过这种方式,所有您的转换都可以放在一个地方,无论您在哪里使用它们。
:::php
$resize = new \GDImage\Transform_Resize_Fit( 300 , 300 );
\GDImage\Transform_Collection::set( 'a_key_for_the_transformation' , clone $resize );
(...)
$image = \GDImage\Factory::import( $import_filepath );
$image->apply( \GDImage\Transform_Collection::get( 'a_key_for_the_transformation' ) );
$final_filepath = \GDImage\Factory::export( $image , $export_filepath );
自定义转换
每个转换都必须实现 \GDImage\Transform_Interface。
请注意,转换应用于资源实例,而不是图像。
:::php
class MyTransform implements \GDImage\Transform_Interface
{
/**
* Apply transformation to a resource.
* Return false if the transformation fails.
*
* @param \GDImage\Resource_Abstract &$rsc
* @return boolean Success flag
* @access public
*/
public function __invoke( \GDImage\Resource_Abstract &$rsc )
{
// your stuff here
return true || false;
}
}
gd_image() 辅助函数
为了简化所有图像导入、转换和导出过程,一个单独的函数可以为你处理所有这些麻烦: gd_image()。
在您的代码中的任何位置调用方法 \GDImage\Config::helper(),gd_image() 函数将在全局命名空间中可用。
此函数接受三个参数
$import:要导入的内容,必填;$export:导出参数,必填但可以是null;$transform:要应用的转换,可选;$failure:在失败时执行或返回的值,可选。
$import
如预期的那样,$import 参数可以是 \GDImage\Factory 可以导入的任何内容:文件路径、数据 URI、Base64 数据、二进制数据等...
与 \GDImage\Factory::import() 方法相比,唯一的区别是没有 MIME 类型转换。
$export
如预期的那样,$export 参数可以是 \GDImage\Factory 可以使用的任何导出内容:文件路径、驱动程序名称、导出参数、驱动程序类名称、驱动程序实例等...
与 \GDImage\Factory::export() 方法相比,第一个区别是没有 MIME 类型转换。
$export 参数还有额外的行为
一个
null导出将导致 文件导出;如果
$export是以 "-" 或 "_" 开头的字符串,则该字符串将被视为 文件导出的后缀;如果
$import是文件路径并且文件导出未指定文件名,文件导出将使用相同的文件名;如果
$import不是一个文件路径并且文件导出未指定文件名,文件导出将使用$import的 MD5 哈希作为文件名;如果
$transform不为 null 并且文件导出未指定文件名或后缀,则转换键 — 或以下划线 "_" 前缀的类名 — 将用作 文件名的后缀;如果
$import是文件路径并且文件导出未指定目录,文件导出将使用相同的目录;如果
$import不是一个文件路径并且文件导出未指定目录,文件导出将使用系统临时目录;如果
$import是具有创建日期的文件路径 — 或 HTTP 中的Last-modified标头 — 并且如果文件导出导致已存在的文件,如果其创建日期高于$import,则不会生成新文件。
这些行为可以相互交互,因此请参阅下面的使用部分以获取更多信息。
$transform
$transform 可以是已注册转换的键、转换类名称(完全限定或位于 \GDImage 命名空间中)、\GDImage 转换类后缀(\GDImage\Transform_*)或转换实例。
请注意,不以 "\" 开头的转换类名称可能对应于 \GDImage 转换而不是全局转换。请小心。
$failure
如果出现问题,将触发 E_USER_WARNING 错误,并返回 false。此行为可以通过 $failure 参数进行自定义
如果
$failure是可调用的,它将被执行,并通过gd_image()辅助函数返回其结果 — 此回调的参数是:抛出的\GDImage\Exception实例、$stuff参数、$export参数和$transform参数;如果
$failure不可调用且不为 null,则它将在失败时用作返回值 — 仍然会触发错误。
使用方法
将文件路径与后缀导出相同
:::php
$final_filepath = gd_image( $import_filepath , '_suffix' [, $transform] );
从转换中导出到相同的文件路径后缀
:::php
$final_filepath = gd_image( $import_filepath , null , 'transform_key' );
$final_filepath = gd_image( $import_filepath , null , $transform );
$final_filepath = gd_image( $import_filepath , null , 'Sepia' );
$final_filepath = gd_image( $import_filepath , null , 'Transform_Negate' );
$final_filepath = gd_image( $import_filepath , null , '\\GDImage\\Transform_Grayscale' );
将文件导出到另一个目录中的转换后缀
:::php
$final_filepath = gd_image( $import , $directory , $transform );
导出到 Base64
:::php
$final_filepath = gd_image( $import , 'base64' [, $transform] );
导出到没有 MIME 类型的数据 URI
:::php
$final_filepath = gd_image( $import , array(
'driver' => 'data' ,
'mimetype' => false ,
) [, $transform] );
AGIF 和 APNG
本库支持动画GIF(AGIF)和动画PNG(APNG)。
“可见”状态
大多数具体的动画图像都是一些优化的结果:移除了多余的像素信息,并将帧减小到最小尺寸。
在这些优化后的动画图像中,实际状态的帧只是噪点像素,无法正确利用。
这就是为什么这个库总是提供“可见”状态的帧:每个分解帧适合图片大小,如果另一个帧应该在后面完成透明像素,它就会这样做。
对于具有混合选项为1(覆盖混合)的APNG帧也是如此:在这种情况下,分解帧是两个帧合并的结果,并且关闭混合选项以避免重新组合错误。
注意,在AGIF中,具有不同调色板的两个帧的合并可能产生256种以上颜色的真彩色帧。
命名
为了方便起见,帧属性从规范中获取其名称。AGIF使用延迟时间(get/setDelayTime())和丢弃方法(get/setDisposalMethod()),而APNG使用延迟分子(get/setDelayNumerator())、延迟分母(get/setDelayDenominator())和丢弃选项(get/setDisposeOption())。
目前没有统一化,也没有计划。
优化
动画图片优化是可行的,但过程非常漫长:每个帧都必须进行分析,与前一帧进行比较,然后减小到其最小尺寸。
默认情况下,优化是禁用的,但可以通过使用\GDImage\Config::setAGifComposerOptimization()或\GDImage\Config::setAPngComposerOptimization()设置来启用。
这些设置是位运算的这些位
1:在帧边缘移除透明像素;2:在帧上移除多余的像素——从丢弃帧到当前帧;borders;4:替换多余的像素——从丢弃帧到当前帧的frame by transparent color.
我们强烈建议在动画图片在后台任务生成时启用动画图片优化,在按需生成时禁用它。
示例
将所有包放到您本地服务器上的gdimage文件夹中,然后您将能够在https:///gdimage/demo/index.php中看到GDImage的实际操作。
如果您想测试特定的图像,只需将其放入demo/samples文件夹中并运行演示。
此外,此项目没有单元测试,但主要测试用例可以从该演示中获得。
接下来是什么?
色度变换
在图片上应用色度变换(双色到N色)应该很酷。
具有X种颜色的图片将转换为具有N种用户定义颜色的图片(没有自动颜色确定,这很烦人)。
为什么不选择Imagick?
托管历史
这个库是为具有Imagick扩展的托管而创建的——是的,有一些。
由于许多库实现了它,因此对于提供Imagick的托管解决方案,这个库可能没有意义。
分而治之
我也不欣赏Imagick的设计方式:将所有东西都放在一个巨大的类中听起来像:“这个类可以调整大小、颜色过滤、文件导出、咖啡、脚部按摩……”
在GDImage库中,有四个基本层:资源句柄GD资源、转换操作资源、图像处理资源和工厂管理图像。这可能不是实现图像操作的最佳方式,但它相对容易维护和扩展。
POOP实现
这是什么POOP?
POOP(许可面向对象编程)是一些建议,主张自愿省略protected和private可见性,仅使用public。
- POOP并不脏
- POOP不是无用的
- POOP不是危险的
- POOP不是困难的
POOP不是废物。
伪受保护属性/方法
该库遵循POOP模式,这意味着每个属性和方法都是public的,即使它们应该被视为protected。
为了区分真正是public的属性/方法和应该被视为protected的属性/方法,需要考虑以下约定:
如果属性/方法以单个下划线 "_" 开头,应视为
pseudo-protected:如果你不清楚自己在做什么,不要使用它。如果属性以两个下划线 "__" 开头,应视为需要特别小心的
pseudo-protected:如果你不确定自己在做什么,不要操作它,因为它可能引起重大问题。如果方法以两个下划线 "__" 开头,它是一个“魔法”PHP方法,可以视为
public。
POOP on \GDImage\Transform_*
你可能注意到,所有的\GDImage\Transform_*类都只有设置器。
实际上,在变换上有获取器似乎没有意义,因为变换只需要参数,当你分配参数时,你已经知道了它们,不是吗?
当然,这些参数中的一些可能在分配之前被操作,所以为了帮助POOP,如果你出错,你仍然可以直接获取它们。
贡献者
- Pierrot Evrard,别名Loops — https://twitter.com/lxxps