- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我最近发现 Imagick 可以支持颜色配置文件,从而生成比 GD 质量更好的图像(有关更多详细信息,请参见 question/answer),因此我正在尝试将我的 GD 包装器移植到改为使用 Imagick 类,我当前的 GD 实现如下所示:
function Image($input, $crop = null, $scale = null, $merge = null, $output = null, $sharp = true)
{
if (isset($input, $output) === true)
{
if (is_string($input) === true)
{
$input = @ImageCreateFromString(@file_get_contents($input));
}
if (is_resource($input) === true)
{
$size = array(ImageSX($input), ImageSY($input));
$crop = array_values(array_filter(explode('/', $crop), 'is_numeric'));
$scale = array_values(array_filter(explode('*', $scale), 'is_numeric'));
if (count($crop) == 2)
{
$crop = array($size[0] / $size[1], $crop[0] / $crop[1]);
if ($crop[0] > $crop[1])
{
$size[0] = round($size[1] * $crop[1]);
}
else if ($crop[0] < $crop[1])
{
$size[1] = round($size[0] / $crop[1]);
}
$crop = array(ImageSX($input) - $size[0], ImageSY($input) - $size[1]);
}
else
{
$crop = array(0, 0);
}
if (count($scale) >= 1)
{
if (empty($scale[0]) === true)
{
$scale[0] = round($scale[1] * $size[0] / $size[1]);
}
else if (empty($scale[1]) === true)
{
$scale[1] = round($scale[0] * $size[1] / $size[0]);
}
}
else
{
$scale = array($size[0], $size[1]);
}
$image = ImageCreateTrueColor($scale[0], $scale[1]);
if (is_resource($image) === true)
{
ImageFill($image, 0, 0, IMG_COLOR_TRANSPARENT);
ImageSaveAlpha($image, true);
ImageAlphaBlending($image, true);
if (ImageCopyResampled($image, $input, 0, 0, round($crop[0] / 2), round($crop[1] / 2), $scale[0], $scale[1], $size[0], $size[1]) === true)
{
$result = false;
if ((empty($sharp) !== true) && (is_array($matrix = array_fill(0, 9, -1)) === true))
{
array_splice($matrix, 4, 1, (is_int($sharp) === true) ? $sharp : 16);
if (function_exists('ImageConvolution') === true)
{
ImageConvolution($image, array_chunk($matrix, 3), array_sum($matrix), 0);
}
}
if ((isset($merge) === true) && (is_resource($merge = @ImageCreateFromString(@file_get_contents($merge))) === true))
{
ImageCopy($image, $merge, round(0.95 * $scale[0] - ImageSX($merge)), round(0.95 * $scale[1] - ImageSY($merge)), 0, 0, ImageSX($merge), ImageSY($merge));
}
foreach (array('gif' => 0, 'png' => 9, 'jpe?g' => 90) as $key => $value)
{
if (preg_match('~' . $key . '$~i', $output) > 0)
{
$type = str_replace('?', '', $key);
$output = preg_replace('~^[.]?' . $key . '$~i', '', $output);
if (empty($output) === true)
{
header('Content-Type: image/' . $type);
}
$result = call_user_func_array('Image' . $type, array($image, $output, $value));
}
}
return (empty($output) === true) ? $result : self::Chmod($output);
}
}
}
}
else if (count($result = @GetImageSize($input)) >= 2)
{
return array_map('intval', array_slice($result, 0, 2));
}
return false;
}
我一直在试验 Imagick 类方法,这是我目前得到的结果:
function Imagick($input, $crop = null, $scale = null, $merge = null, $output = null, $sharp = true)
{
if (isset($input, $output) === true)
{
if (is_file($input) === true)
{
$input = new Imagick($input);
}
if (is_object($input) === true)
{
$size = array_values($input->getImageGeometry());
$crop = array_values(array_filter(explode('/', $crop), 'is_numeric'));
$scale = array_values(array_filter(explode('*', $scale), 'is_numeric'));
if (count($crop) == 2)
{
$crop = array($size[0] / $size[1], $crop[0] / $crop[1]);
if ($crop[0] > $crop[1])
{
$size[0] = round($size[1] * $crop[1]);
}
else if ($crop[0] < $crop[1])
{
$size[1] = round($size[0] / $crop[1]);
}
$crop = array($input->getImageWidth() - $size[0], $input->getImageHeight() - $size[1]);
}
else
{
$crop = array(0, 0);
}
if (count($scale) >= 1)
{
if (empty($scale[0]) === true)
{
$scale[0] = round($scale[1] * $size[0] / $size[1]);
}
else if (empty($scale[1]) === true)
{
$scale[1] = round($scale[0] * $size[1] / $size[0]);
}
}
else
{
$scale = array($size[0], $size[1]);
}
$image = new IMagick();
$image->newImage($scale[0], $scale[1], new ImagickPixel('white'));
$input->cropImage($size[0], $size[1], round($crop[0] / 2), round($crop[1] / 2));
$input->resizeImage($scale[0], $scale[1], Imagick::FILTER_LANCZOS, 1); // $image->scaleImage($scale[0], $scale[1]);
//if (in_array('icc', $image->getImageProfiles('*', false)) === true)
{
$version = preg_replace('~([^-]*).*~', '$1', ph()->Value($image->getVersion(), 'versionString'));
if (is_file($profile = sprintf('/usr/share/%s/config/sRGB.icm', str_replace(' ', '-', $version))) !== true)
{
$profile = 'http://www.color.org/sRGB_v4_ICC_preference.icc';
}
if ($input->profileImage('icc', file_get_contents($profile)) === true)
{
$input->setImageColorSpace(Imagick::COLORSPACE_SRGB);
}
}
$image->compositeImage($input, Imagick::COMPOSITE_OVER, 0, 0);
if ((isset($merge) === true) && (is_object($merge = new Imagick($merge)) === true))
{
$image->compositeImage($merge, Imagick::COMPOSITE_OVER, round(0.95 * $scale[0] - $merge->getImageWidth()), round(0.95 * $scale[1] - $merge->getImageHeight()));
}
foreach (array('gif' => 0, 'png' => 9, 'jpe?g' => 90) as $key => $value)
{
if (preg_match('~' . $key . '$~i', $output) > 0)
{
$type = str_replace('?', '', $key);
$output = preg_replace('~^[.]?' . $key . '$~i', '', $output);
if (empty($output) === true)
{
header('Content-Type: image/' . $type);
}
$image->setImageFormat($type);
if (strcmp('jpeg', $type) === 0)
{
$image->setImageCompression(Imagick::COMPRESSION_JPEG);
$image->setImageCompressionQuality($value);
$image->stripImage();
}
if (strlen($output) > 0)
{
$image->writeImage($output);
}
else
{
echo $image->getImageBlob();
}
}
}
return (empty($output) === true) ? $result : self::Chmod($output);
}
}
else if (count($result = @GetImageSize($input)) >= 2)
{
return array_map('intval', array_slice($result, 0, 2));
}
return false;
}
已经支持基本功能(裁剪/调整大小/水印),但是,我仍然遇到一些问题。由于 PHP Imagick 文档有点糟糕,我别无选择,只能尝试所有可用方法和参数的试错法组合,这会花费很多时间。
我目前的问题/疑惑是:
在我最初的实现中,行:
ImageFill($image, 0, 0, IMG_COLOR_TRANSPARENT);
ImageSaveAlpha($image, true);
ImageAlphaBlending($image, true);
具有preserving the transparency的效果当您将透明的 PNG 图像转换为 PNG 输出时。但是,如果您尝试将透明的 PNG 图像转换为 JPEG 格式,则透明像素的颜色应设置为白色。到目前为止,使用 ImageMagick,我只能 convert all transparent pixels to white , 但如果输出格式支持,我就无法保留透明度。
我的原始实现在 PNG 上使用 9 的压缩级别,在 JPEG 上使用 90 的质量:
foreach (array('gif' => 0, 'png' => 9, 'jpe?g' => 90) as $key => $value)
线条:
$image->setImageCompression(Imagick::COMPRESSION_JPEG);
$image->setImageCompressionQuality($value);
$image->stripImage();
似乎可以压缩 JPEG 图像 - 然而,GD 能够使用相同的 $value
作为质量参数将其压缩得更多 - 为什么?我也对以下之间的差异一无所知:
Imagick::setCompression()
/Imagick::setImageCompression()
和Imagick::setCompressionQuality()
/Imagick::setImageCompressionQuality()
我应该使用哪一个,它们有什么区别?此外,最关键的问题与 PNG 压缩有关,列表 Imagick compression constants似乎不支持 PNG 格式:
imagick::COMPRESSION_UNDEFINED (integer)
imagick::COMPRESSION_NO (integer)
imagick::COMPRESSION_BZIP (integer)
imagick::COMPRESSION_FAX (integer)
imagick::COMPRESSION_GROUP4 (integer)
imagick::COMPRESSION_JPEG (integer)
imagick::COMPRESSION_JPEG2000 (integer)
imagick::COMPRESSION_LOSSLESSJPEG (integer)
imagick::COMPRESSION_LZW (integer)
imagick::COMPRESSION_RLE (integer)
imagick::COMPRESSION_ZIP (integer)
imagick::COMPRESSION_DXT1 (integer)
imagick::COMPRESSION_DXT3 (integer)
imagick::COMPRESSION_DXT5 (integer)
这是在屁股上画画,因为如果使用 Imagick 输出(大小约为 2 MB),恰好大小为 100-200 KB 的 GD PNG 输出会变得非常胖...
有a couple of questions on SO regarding this issue ,但我一直无法找到任何不依赖外部应用程序的有效解决方案。这真的不可能用 ImageMagick 来做吗?!
在 GD 实现中,我调用 ImageConvolution()
来稍微锐化图像,我知道 Imagick 有内置的锐化图像的方法(我还没有机会尝试它们yet) 但我想知道 Imagick 是否具有与 ImageConvolution()
函数等效的功能。
这与原来的实现无关,但我也想把它弄好。
我应该始终将 Imagick/International Color Consortium sRGB 颜色配置文件添加到所有图像吗?还是应该仅在存在(或不存在)特定颜色配置文件时才添加?
另外,我应该删除现有的颜色配置文件吗?
我知道这可能是一个广泛的问题,但我对颜色配置文件的理解非常有限,非常感谢对此提供一些一般性指导。
GD 原生支持打开远程图像,可以通过 ImageCreateFrom*
函数,也可以使用 file_get_contents()
结合 ImageCreateFromString()
,例如我在做。
Imagick 似乎只能打开本地镜像,或打开文件句柄。有什么直接的方法可以让 Imagick 读取远程图像(无需打开和关闭文件句柄)?
如果有人可以阐明这些问题中的任何一个,我将不胜感激。
提前致谢!
最佳答案
您的 PNG 图像尺寸可能会增加的原因有很多,您将遇到的最明显的一个原因是 GM/IM 无法将透明度作为 tRNS block (基本上是 PNG 图像的 bool 透明度)。不幸的是,GraphicsMagick 和 ImageMagick 的维护者还没有实现这个特性。我与他们交换了电子邮件,所以我肯定知道这一点。
我知道您不想使用外部工具,但请相信我您会这样做。 Image/GraphicsMagick 在压缩 PNG 图像方面真的很糟糕。我使用的解决方案是,使用 GraphicsMagick 来操作图像,并检查图像是否包含透明像素,如果确实包含透明像素,则在图像上运行 OptiPNG。 OptiPNG 将看到透明度可以作为 tRNS block 传送并采取相应行动。实际上,您应该在使用 Image/GraphicsMagick 后对所有 PNG 图像运行 OptiPNG,因为我发现您可以获得更大的压缩率。您还可以通过关闭抖动和使用 YUV 颜色空间来节省空间。
至于GM比IM更好地缩小图像尺寸,你应该知道GM默认使用8位色彩空间来缩小图像,而ImageMagick默认使用16位。这就是为什么在将图像颜色减少到超过 255 种颜色的值时 GM 比 IM 快得多的原因。也许你应该检查压缩后每个图像中的颜色数来确认。
关于php - 将 PHP/GD 包装器移植到 Imagick 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5818603/
在本地主机上,该库运行良好,当在生产环境中调用该函数时,php 会抛出一个 fatal error 。 我检查了那里的 phpinfo(),它已启用。 我想看看是否可以在 php.ini 上添加任何内
当我在“配置命令”中的 phpinfo() 输出显示时,如何启用(或者我可能需要安装)GD; --without-gd ? 我的 phpinfo() 输出“Core”中也没有任何内容,其中列出了“gd
当我在“配置命令”中的 phpinfo() 输出显示时,如何启用(或者我可能需要安装)GD; --without-gd ? 我的 phpinfo() 输出“Core”中也没有任何内容,其中列出了“gd
我正在尝试使用 GD 函数:imagettfbbox(),但它未定义。自从我在 Ubuntu 21.10 上以来,我已经编译了我自己的带有 argon2 支持的 PHP 版本。 我是这样配置的: ./
我正在尝试使用 GD 函数:imagettfbbox(),但它未定义。自从我在 Ubuntu 21.10 上以来,我已经编译了我自己的带有 argon2 支持的 PHP 版本。 我是这样配置的: ./
我已经通过一些在线资源自学了机器学习,但我有一个关于梯度下降的问题,但我无法弄清楚。 梯度下降的公式由以下逻辑回归给出: Repeat { θj = θj−α/m∑(hθ(x)−y)xj }
我在 centos 7 服务器和 nginx 网络服务器上使用 laravel 网络框架,我安装了 php71w-gd,但当我想上传文件时仍然出现此错误 Intervention \ Image \
我正在尝试安装 moodle,但它显示缺少/应该启用 php-gd 扩展。然而,gd 已经安装并且是最新的,当我命令 php -v 时,我收到以下错误,如下所示。 PHP Warning: PHP
编译最新的2.0.35版本,用默认的 ./configure编译 当make的时候,出现以下错误 configure.ac:64: error: possibly undefined macro
我有一个函数可以用来接受用户上传的图像,按比例将其缩放到最大宽度/高度为 4,000 像素,还可以生成 400 像素和 800 像素的缩略图。它需要能够处理透明的 PNG 并应用白色背景。 我当前的代
我试图弄清楚为什么我无法在我的 Debian 7 服务器上安装 GD perl 模块。这是我安装核心内容的方式: sudo apt-get install libgd-gd2-perl 然后运行
如何使用 PHP GD 库制作清晰度滤镜? 所以这... 转向这个... 如果用 PHP 做不到,还有什么其他语言可以做到? 最佳答案 我认为他想使用 PHP 的 GD 库。这很简单:function
我尝试使用 php gd 创建验证码图像: $im = imagecreatetruecolor(100, 25); $white = imagecolorallocate($im, 255, 255
我在网上找到了一些关于 PHP+GD 图像处理的内容,但似乎没有一个能给我我想要的东西。 我让人上传任意尺寸的图像,我编写的脚本将图像大小调整为不超过 200 像素宽 x 200 像素高,同时保持宽高
你好, 我试图围绕中心旋转一个圆形图像,然后切掉边。我看到了 imagerotate 函数,但它似乎没有围绕中心旋转。 有人有什么建议吗? 谢谢。 更新:由于它是一个圆,我想剪掉边缘并使我的圆保持相同
我正在尝试在特定图像上添加文本。它工作完美,但图像质量较低,尤其是 papyrus.ttf 字体。如何提高图像中文本的质量。但我需要高质量来打印输出。这是我的代码..它非常简单。 header("Co
我正在使用 jQuery 的 imgAreaSelect插件,以便裁剪图像并保存缩略图以在比例发生变化等情况下使用。不幸的是,结果与我的预期相去甚远,而且我无法做到正确。图像整体调整大小,而不是被裁剪
好吧,一个小背景故事。我正在重新设计我的一个旧网站,我想使用 Myriad Pro对于页面上的标题。这对于 PHP 等将是动态的。 起初我认为我应该只使用 CSS 样式并将 Myriad 定义为主要字
我想使用 GD 裁剪图像,但我希望它围绕特定形状裁剪,而不仅仅是一个正方形。 这可能吗? 最佳答案 一种方法是创建一个所需正方形大小的蒙版,其中包含一个透明的 alpha channel 。然后将其放
在 PHP GD 中,如何在不丢失任何的情况下将真彩色图像转换为调色板 颜色。用imagetruecolortopallete它不起作用。我有一个函数可以遍历所有颜色并过滤它们(例如灰度)。而且它不会
我是一名优秀的程序员,十分优秀!