使用 PHP Imagick 将 ICO 转换为 PNG
Convert ICO to PNG using PHP Imagick
我目前正在尝试使用 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 文件。我已经阅读了 Wikipedia entry for ICO files 并且和往常一样,它是一团乱七八糟的封闭源 Microsoft 东西。我不知道它们是按某种顺序出现的……最小的在前,还是最大的在前,所以我认为我的建议是按照您的计划简单地遍历 ICO 文件中的所有图像,并获得最大的图像像素数并将其调整为 16x16。
原答案
太多的评论,也许还不够回答...我根本不使用 PHP Imagick,但是如果你使用 ImageMagick 在终端的命令行中,您可以设置 ICO 大小,如 this:
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);
我目前正在尝试使用 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 文件。我已经阅读了 Wikipedia entry for ICO files 并且和往常一样,它是一团乱七八糟的封闭源 Microsoft 东西。我不知道它们是按某种顺序出现的……最小的在前,还是最大的在前,所以我认为我的建议是按照您的计划简单地遍历 ICO 文件中的所有图像,并获得最大的图像像素数并将其调整为 16x16。
原答案
太多的评论,也许还不够回答...我根本不使用 PHP Imagick,但是如果你使用 ImageMagick 在终端的命令行中,您可以设置 ICO 大小,如 this:
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);