Конвертировать ICO в PNG используя PHP Imagick - PullRequest
1 голос
/ 25 апреля 2020

В настоящее время я пытаюсь преобразовать файл ICO в PNG размером 16x16 пикселей, используя 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);
$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: мне нужен простой способ конвертировать файл ICO любого размера в PNG размером 16x16 пикселей, используя 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);

Ответы [ 2 ]

1 голос
/ 25 апреля 2020

Обновленный ответ

При повторном чтении вопроса кажется, что вы действительно хотите создать файл PNG из файла ICO. Я прочитал запись Википедии для файлов ICO и, как обычно, это плохо определенный сложный беспорядок в материалах 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 , но, надеюсь, вы сможете решить это отсюда.

0 голосов
/ 28 апреля 2020

Мое окончательное решение:

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