使用PHP Imagick将ICO转换为PNG

时间:2020-04-25 14:01:05

标签: php imagemagick imagick ico

我目前正在尝试使用PHP-Imagick将ICO文件转换为16x16 px 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文件

  • favicon-0.png
  • favicon-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:我需要一种简单的方法,使用PHP-Imagick(不选择使用GD)将任何大小的ICO文件转换为16x16 px PNG。

更新

我的解决方案(目前可以使用,但可能不是最佳选择):

<?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);

2 个答案:

答案 0 :(得分:1)

更新后的答案

在重新阅读您的问题时,似乎您实际上是想从ICO文件制作PNG文件。我已经读过Wikipedia entry for ICO files,并且像往常一样,它是闭源Microsoft资料中指定不当的复杂混乱。我无法确定它们是按某种顺序排列的。.最小的优先,或者最大的优先,所以我认为我的建议是按照您的计划简单地遍历ICO文件中的所有图像,并获得最大的图像。像素数并将其大小调整为16x16。

原始答案

太多评论了,也许还不足以回答...我完全没有使用PHP Imagick ,但是如果您在 ImageMagick 在终端的命令行中,您可以设置ICO大小,例如this

in_header

说出要嵌入到输出文件中的分辨率。正如我说的,我不使用PHP,但是我相信等效的东西是这样的:

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

对不起,我无能为力,我只是没有设置使用PHP和 Imagick ,但希望您可以从这里解决问题。

答案 1 :(得分:0)

我的最终解决方案:

<?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);
相关问题