imageaffine

(PHP 5 >= 5.5.0, PHP 7, PHP 8)

imageaffine返回包含使用可选剪切区域对源图像进行仿射变换后的图像

描述

imageaffine(GdImage $image, array $affine, ?array $clip = null): GdImage|false

警告

此函数目前没有文档记录;只有其参数列表可用。

参数

image

一个 GdImage 对象,由图像创建函数之一返回,例如 imagecreatetruecolor().

affine

带有键 0 到 5 的数组。

clip

带有键 "x"、"y"、"width" 和 "height" 的数组;或 null.

返回值

成功时返回仿射变换后的图像对象,失败时返回 false.

变更日志

版本 描述
8.0.0 clip 现在可以为空。
8.0.0 成功时,此函数现在返回 GDImage 实例;以前,返回 resource.
添加笔记

用户贡献笔记 5 个笔记

25
abc at ed48 dot com
10 年前
仿射变换是涉及矩阵的几何变换操作,涵盖 2D 和 3D 环境。
变换常用于线性代数和计算机图形学。

在图像的几何变换中,像素坐标被映射。

这意味着每个像素都由图像矩形域中的两个坐标定位。
在不详细介绍像素映射的情况下,让我们来看看真正重要的是什么:仿射变换。
像素映射有几种类别,其中一种称为“仿射”。
仿射变换包括:缩放、旋转、倾斜和平移。

PHP 5.5.0+,如“libart”,使用六个浮点元素的数组来完成这项工作。

仿射数组定义如下,

$affine = [ a0, a1, b0, b1, a2, b2 ];

其中,
a0、a1、b0、b1、a2、b2 是浮点值。

用等式表示,

x' = a0x + a1y + a2

y' = b0x + b1y + b2

a) 恒等变换,对点路径不做任何改变,

$affine = [ 1, 0, 0, 1, 0, 0 ];

等式重新映射,

x' = 1x + 0y + 0 = x

y' = 0x + 1y = 0 = y

b) 平移,

$affine = [ 1, 0, 0, 1, H, V ];

等式重新映射,

x' = 1x + 0y + H = x + H

y' = 0x + 1y = V = y + V

每个点水平移动 H 个单位,垂直移动 V 个单位。

c) 缩放,

$affine = [ i, 0, j, 1, 0, 0 ];

等式重新映射,

x' = Mx + 0y + 0 = Mx

y' = 0x + Ny = 0 = Ny

每个点会根据 M 和 N 水平或垂直拉伸或压缩其路径;负值或正值。

d) 倾斜,平行于 x 轴,

$affine = [ 1, K, 0, 1, 0, 0 ];

等式重新映射,

x' = 1x + Ky + 0 = x + Ky

y' = 0x + 1y = 0 = y

倾斜,平行于 y 轴,

$affine = [ K, 0, 0, 1, 0, 0 ];

等式重新映射,

x' = 1x + 0y + 0 = x

y' = Kx + 1y = 0 = y + Kx

e) 旋转,顺时针,

$affine = [ cos Ø, sin Ø, -sin Ø, cos Ø, 0, 0 ];

等式重新映射,

x' = x cos Ø + y sin Ø + 0 = x cos Ø + y sin Ø

y' = -x sin Ø + y cos Ø = 0 = y cos Ø - x sin Ø

旋转,逆时针,

$affine = [ cos Ø, -sin Ø, sin Ø, cos Ø, 0, 0 ];

等式重新映射,

x' = x cos Ø - y sin Ø + 0 = x cos Ø - y sin Ø

y' = x sin Ø + y cos Ø = 0 = y sin Ø - x cos Ø
5
abc at ed48 dot com
10 年前
这是一个示例,它在每次执行时都会执行特定处理

<?php

if (!function_exists('imageaffine'))
{
echo
'FUNCTION NOT DEFINED IN THIS VERSION OF PHP';
exit;
}

$base_img = 'affine.png';

$tgt_img1 = 'triangle1.png';

$tgt_img2 = 'triangle2.png';

$arr_affine = [
[
1, 0, 0, 1, 0, 0 ],
[
1, 0, 0, 1, 150, 0 ],
[
1.2, 0, 0, 0.6, 0, 0 ],
[ -
1.2, 0, 0, -0.6, 0, 0 ],
[
1, 2, 0, 1, 0, 0 ],
[
2, 1, 0, 1, 0, 0 ],
[
cos(15), sin(15), -sin(15), cos(15), 0, 0 ],
[
cos(15), -sin(15), sin(15), cos(15), 0, 0 ]
];

$RSR_base = imagecreatetruecolor(400, 300);
$w = imagesx($RSR_base);
$h = imagesy($RSR_base);

$arr_clip = [ 'x' => 0, 'y' => 0, 'width' => $w, 'height' => $h ];

$fillcolor = imagecolorallocate($RSR_base, 0, 0, 0);

imagefill($RSR_base, 10,10, $fillcolor);

imagepng($RSR_base, $base_img);

$drawcolor = imagecolorallocate($RSR_base, 255, 0, 0);

$triangle = [ 50, 50, 50, 150, 200, 150 ];
$points = 3;

imageantialias($RSR_base, 1);

$drawtriangle = imagefilledpolygon($RSR_base, $triangle, $points, $drawcolor);

imagepng($RSR_base, $tgt_img1);

$select = mt_rand(0, 7);

$RSRaff2 = imageaffine($RSR_base, $arr_affine[$select], $arr_clip);

imagepng($RSRaff2, $tgt_img2, 9);

?>

支持图像<br><br>
<img src="<?php echo $base_img; ?>" alt="*" /><br><br>

基础图像<br><br>
<img src="<?php echo $tgt_img1; ?>" alt="*" /><br><br>

结果图像<br><br>
<img src="<?php echo $tgt_img2; ?>" alt="*" />
2
adri at sternschanze dot net
6 年前
更正

仿射数组定义如下,

$affine = [ a0, b0, a1, b1, a2, b2 ];
3
abc at ed48 dot com
10 年前
纠正

c) 缩放,

$affine = [ M, 0, N, 1, 0, 0 ];

等式重新映射,

x' = Mx + 0y + 0 = Mx

y' = 0x + Ny = 0 = Ny

每个点会根据 M 和 N 水平或垂直拉伸或压缩其路径;负值或正值。
0
der at herrstrietzel dot de
3 年前
可能存在替代方案或解决方法,因为 imageaffine 支持更复杂的插值方法,例如 IMG_MITCHELL。

// 创建图像资源
$img_path = 'test.jpg';
$img = imagecreatefromstring(file_get_contents($img_path));
// 使用 Mitchell 插值将图像缩放到 50%
$scale = 0.5;
imagesetinterpolation($img, IMG_MITCHELL);
$img_scaled = imageaffine($img, [0.5, 0, 0, 0.5, 0, 0]);
// 保存图像
$output = 'test_scaledAffine.png';
imagepng($img_scaled, $output, 9);
echo '<img src="'.$output.'" width="300">';

辅助函数示例

function scaleImgAffine($img, $newWidth, $resized_file='', $interpolation=IMG_MITCHELL)
{
// 如果 $img 是文件路径,则创建 img 资源
if(!is_resource($img)){
$img = imagecreatefromstring(file_get_contents($img));
}
// 获取原始 img 尺寸
$w = imagesx($img);
$h = imagesy($img);

/**
* 建议的插值方法是 'IMG_MITCHELL'
* 为大多数图像类型提供最佳精度和
* 压缩效果
* 特别是对于带有透明度的 png,它可以防止
* 降采样结果出现伪影
*/
imagesetinterpolation($img, $interpolation);
/*
* imageaffine 会以变形的方式缩放尺寸 -
* 即使是基于正方形的图像
* 1200x1200 会得到类似于 1199x1200 的结果
* - 非常欢迎改进
* 解决方法:调整原始宽度和剪切参数
* 为我解决了问题,方法是增加 1px
*/
$scale = ($newWidth+1) / $w;
$newHeight = floor($h*$scale);

// 通过仿射矩阵进行缩放
$resized_affine =
imageaffine(
$img,
[$scale, 0, 0, $scale, 0, 0],
['x' => 0, 'y' => 0, 'width' => $w, 'height' => $h-1]
);
/*
* 'clip' 参数可能具有误导性,因为它期望
* 原始宽度而不是最终/转换后的宽度
*/

// 保存到文件或返回资源
if($resized_file){
$file_type = pathinfo($resized_file, PATHINFO_EXTENSION );
switch($file_type){
case 'jpg'
case 'jpeg'
// 为 jpg 平铺透明度
$tmp_img = imagecreatetruecolor($newWidth, $newHeight );
$bg = imagecolorallocate($tmp_img, 255,255,255);
imagefill($tmp_img, 0, 0, $bg);
imagesavealpha($tmp_img, false);
imagealphablending($tmp_img, true);
imagecopy($tmp_img, $resized_affine, 0, 0, 0, 0, $newWidth, $newHeight );
imagejpeg($tmp_img, $resized_file, 85);
break;
case 'png'
imagepng($resized_affine, $resized_file, 9);
break;
}
}else{
return $resized_affine;
}
}

$img_scaled_affine = scaleImgAffine($img_path, 400, 'test_scaledAffine.jpg', true);

IMG_MITCHELL 在 GDlib 环境中(... 实际上是 png31 由于 gds alpha 7 位通道?)处理带有透明度的 png24 缩放时特别先进。最常见的是,由于调整大小后不可察觉的伪影,您会遇到使用 png 的压缩效果不佳的问题。

希望我们能看到更先进的插值方法在像 imagecopyresized 或 imagescale 这样的基本 GD 调整大小函数中的实现。
To Top