18

PNG (および JPEG) 画像を自分のサイトにアップロードしています。

それらは静的でなければなりません (つまり、1 フレーム)。

APNGのようなものがあります。

弾むボール

(Firefoxでアニメーション化されます)。

ウィキペディアの記事によると……

APNG は、APNG を認識しないアプリケーションがそれらを無視するような方法で、PNG 補助チャンク内の後続のフレームを非表示にしますが、それ以外の場合、ソフトウェアがアニメーション化された画像とアニメーション化されていない画像を区別できるようにするための形式への変更はありません。

これは、PNG がコードでアニメーション化されているかどうかを判断できないということですか?

可能であれば、PHP に関する正しい方向 (GD、ImageMagick) を教えてください。

4

4 に答える 4

19

APNG 画像は、サポートしていない読者のために PNG として「カモフラージュ」されるように設計されています。つまり、リーダーがそれらをサポートしていない場合、通常の PNG ファイルであると想定し、最初のフレームのみを表示します。つまり、それらは PNG と同じ MIME タイプ (image/png) を持ち、同じマジック ナンバー ( 89 50 4e 47 0d 0a 1a 0a) を持ち、通常は同じ拡張子で保存されます (ただし、これはファイル タイプを確認する良い方法ではありません)。 )。

では、それらをどのように区別しますか?APNGには「acTL」チャンクが含まれています。そのため、文字列acTL(または 16 進数) 61 63 54 4C(チャンク マーカー (つまり00 00 00 08) の前の 4 バイトは、ビッグ エンディアン形式のチャンクのサイズです。 field)) あなたはかなり上手なはずです。さらに良くするには、このチャンクが「IDAT」チャンクの最初の発生の前に表示されることを確認します (単に を探しますIDAT)。

このコード ( http://foone.org/apng/identify_apng.phpから取得) はトリックを行います:

<?php
# Identifies APNGs
# Written by Coda, functionified by Foone/Popcorn Mariachi#!9i78bPeIxI
# This code is in the public domain
# identify_apng returns:
# true if the file is an APNG
# false if it is any other sort of file (it is not checked for PNG validity)
# takes on argument, a filename.
function identify_apng($filename)
    {
    $img_bytes = file_get_contents($filename);
    if ($img_bytes)
        {
        if(strpos(substr($img_bytes, 0, strpos($img_bytes, 'IDAT')), 
                 'acTL')!==false)
            {
        return true;
        }
        }
    return false;
    }
?>
于 2010-12-24T08:46:28.820 に答える
6

私の知る限り、APNG をサポートしていないライブラリは、PNG の最初のフレームだけを取得します。あなたの場合、APNG (または PNG、JPEG など) から新しい画像を作成し、PNG として再保存することができます。ライブラリが APNG をサポートするように更新されていない限り、GD を使用している場合はアニメーション データを削除する必要があります。

于 2010-12-24T08:41:24.020 に答える
3

ファイル全体が非常に大きくなる可能性があるため、ファイル全体を読み取らず、IDAT ルールの前に acTL に依存する、より最適化されたバージョンを提案したいと思います。

function identify_apng($filepath) {
    $apng = false;

    $fh = fopen($filepath, 'r');
    $previousdata = '';
    while (!feof($fh)) {
        $data = fread($fh, 1024);
        if (strpos($data, 'acTL') !== false) {
            $apng = true;
            break;
        } elseif (strpos($previousdata.$data, 'acTL') !== false) {
            $apng = true;
            break;
        } elseif (strpos($data, 'IDAT') !== false) {
            break;
        } elseif (strpos($previousdata.$data, 'IDAT') !== false) {
            break;
        }

        $previousdata = $data;
    }

    fclose($fh);

    return $apng;
}

ファイルの大きさに応じて速度が 5 倍から 10 倍以上に向上し、メモリの使用量も大幅に削減されます。

注意: これは、fread に指定されたサイズで、または前のチャンクと現在のチャンクを連結して、さらに微調整できる可能性があります。ちなみに、acTL/IDAT ワードは 2 つの読み取りチャンクに分割される可能性があるため、この連結が必要です。

于 2018-10-07T11:17:20.233 に答える