使用PHP Imagick将ICO转换为PNG



我目前正在尝试使用PHP Imagick将ICO文件转换为16x16像素的PNG。到目前为止我尝试过的:

<?php
if (empty(Imagick::queryFormats("ICO"))) {
throw new Exception('Unsupported format');
}
$sourceFile = __DIR__ . '/favicon.ico';
$targetFile = __DIR__ . '/favicon.png';
$im = new Imagick($sourceFile);
$im->writeImages($targetFile, true);

这部分起作用。问题是,一个ICO文件可能包含多个图像,因此上面的代码创建了多个PNG文件

  • 收藏夹-0.png
  • 收藏夹-1.png

适用于各种尺寸。这是可以的,但是,我需要找到一个接近16x16像素的,缩小(如果需要(并删除所有其他像素的可能性。为此,我已经尝试了一些东西,这就是我目前陷入困境的地方:

<?php
if (empty(Imagick::queryFormats("ICO"))) {
throw new Exception('Unsupported format');
}
$sourceFile = __DIR__ . '/favicon.ico';
$targetFile = __DIR__ . '/favicon.png';
$im = new Imagick($sourceFile);
$count = $im->getNumberImages();
if ($count > 1) {
for ($x = 1; $x <= $count; $x++) {
$im->previousImage();
$tmpImageWidth = $im->getImageWidth();
$tmpImageHeight = $im->getImageHeight();
// ???
}
}
$im->writeImages($targetFile, true);

我想,我会找到一种尝试和错误的工作方式。但我想知道,是否有更简单的方法来实现这一点。

TL;DR:我需要一种简单的方法来将任何大小的ICO文件转换为16x16像素的PNG,使用PHP Imagick(使用GD不是一种选择(。

更新:

我的(目前正在工作,但可能次优(解决方案:

<?php
if (empty(Imagick::queryFormats("ICO"))) {
throw new Exception('Unsupported format');
}
$sourceFile = __DIR__ . '/favicon.ico';
$targetFile = __DIR__ . '/favicon.png';
$im = new Imagick($sourceFile);
$count = $im->getNumberImages();
$targetWidth = $targetHeight = 16;
if ($count > 1) {
$images = [];
for ($x = 1; $x <= $count; $x++) {
$im->previousImage();
$images[] = [
'object' => $im,
'size' => $im->getImageWidth() + $im->getImageHeight()
];
}
$minSize = min(array_column($images, 'size'));
$image = array_values(array_filter($images, function($image) use ($minSize) {
return $minSize === $image['size'];
}))[0];
$im = $image['object'];
if ($image['size'] <> $targetWidth + $targetHeight) {
$im->cropThumbnailImage($targetWidth, $targetHeight);
}
}
else {
if ($im->getImageWidth() <> $targetWidth || $im->getImageHeight() <> $targetHeight) {
$im->cropThumbnailImage($targetWidth, $targetHeight);
}
}
$im->writeImage($targetFile);

更新的答案

在重读你的问题时,你似乎真的想从ICO文件中制作一个PNG文件。我读过维基百科上ICO文件的条目,和往常一样,它是一个由微软的封闭源代码组成的复杂混乱的条目。我不知道他们是不是按顺序来的。。最小优先,或者最大优先,所以我认为我的建议是,按照你的计划,简单地迭代ICO文件中的所有图像,得到像素数最多的图像,并将其调整为16x16。

原始答案

评论太多了,也许还不够回答。。。我根本不怎么使用PHPImagick,但如果你在终端的命令行中使用ImageMagick

magick INPUT -define icon:auto-resize="256,128,96,64,16" output.ico

以说明您希望在输出文件中嵌入的分辨率。正如我所说,我不使用PHP,但我相信它的等价物是:

$imagick->setOption('icon:auto-resize', "16");

很抱歉,我帮不上什么忙,我只是没有设置使用PHP和Imagick,但希望你能从这里解决这个问题。

我的最终解决方案:

<?php
if (empty(Imagick::queryFormats("ICO"))) {
throw new Exception('Unsupported format');
}
$sourceFile = __DIR__ . '/favicon.ico';
$targetFile = __DIR__ . '/favicon.png';
$im = new Imagick($sourceFile);
$count = $im->getNumberImages();
$targetWidth = $targetHeight = 16;
if ($count > 1) {
$images = [];
for ($x = 1; $x <= $count; $x++) {
$im->previousImage();
$images[] = [
'object' => $im,
'size' => $im->getImageWidth() + $im->getImageHeight()
];
}
$minSize = min(array_column($images, 'size'));
$image = array_values(array_filter($images, function($image) use ($minSize) {
return $minSize === $image['size'];
}))[0];
$im = $image['object'];
if ($image['size'] <> $targetWidth + $targetHeight) {
$im->cropThumbnailImage($targetWidth, $targetHeight);
}
}
else {
if ($im->getImageWidth() <> $targetWidth || $im->getImageHeight() <> $targetHeight) {
$im->cropThumbnailImage($targetWidth, $targetHeight);
}
}
$im->writeImage($targetFile);

最新更新