現在の位置: ホーム> 最新記事一覧> PNGファイルヘッダー:pack() +ファイル構造分析

PNGファイルヘッダー:pack() +ファイル構造分析

M66 2025-05-28

画像処理の分野では、PNG(ポータブルネットワークグラフィックス)は、広く使用されているロスレス圧縮画像形式です。そのファイル構造には、それぞれが特定の画像またはメタデータ情報を含む複数の「チャンク」を含む明確な仕様があります。これらの構造を理解することは、カスタム画像処理ツールの開発に役立つだけでなく、バ​​イナリデータ操作とプロトコル設計の学習にも大きなメリットがあります。

この記事では、PHPのpack()およびunpack()機能を介してPNGファイルのヘッダーを手動で解析し、その構造を分析します。 PHPはWebベースの言語ですが、バイナリデータの処理にも優れた能力があります。

1。PNGファイル構造の概要

法的PNGファイルは、8バイトの固定署名から開始する必要があります。

 89 50 4E 47 0D 0A 1A 0A

次は1つ以上のブロック(チャンク)で、それぞれが次の部分で構成されています。

  • 長さ(4バイト) - データパーツの長さ

  • ブロックタイプ(4バイト) - IHDR、IDAT、IENDなど。

  • ブロックデータ(変数)

  • CRC検証(4バイト)

2. PHPを使用して、PNGファイルヘッダーを解析します

次の例コードでは、PNGファイルの最初のいくつかのバイトを読み取り、ファイルヘッダーと最初のブロック(通常はIHDR)を抽出します。

 <?php
$filename = 'https://m66.net/sample.png';

// ファイルを読む前に 33 バイト:8 バイトサイン + 4+4+13+4(IHDR 総ブロック長)
$data = file_get_contents($filename, false, null, 0, 33);

if ($data === false || strlen($data) < 33) {
    die("読むことができません PNG 小さいファイルまたはファイルが小さすぎます。");
}

// 分析 PNG サイン
$signature = substr($data, 0, 8);
$expectedSignature = "\x89PNG\r\n\x1a\n";

if ($signature !== $expectedSignature) {
    die("これは有効なものではありません PNG 書類。");
}

echo "PNG サイン验证成功。\n";

// 分析第一个 Chunk(あるべきです IHDR)
$chunkData = substr($data, 8);

// 使用 unpack フィールドを抽出します
$unpacked = unpack("Nlength/A4type", substr($chunkData, 0, 8));
$length = $unpacked['length'];
$type = $unpacked['type'];

echo "最初のブロックタイプ: $type\n";
echo "データの長さ: $length\n";

// 抽出する IHDR データ
$ihdrData = substr($chunkData, 8, 13);

$ihdr = unpack("Nwidth/Nheight/CbitDepth/CcolorType/Ccompression/Cfilter/Cinterlace", $ihdrData);

echo "幅: {$ihdr['width']} px\n";
echo "高い: {$ihdr['height']} px\n";
echo "深い: {$ihdr['bitDepth']}\n";
echo "カラータイプ: {$ihdr['colorType']}\n";
echo "圧縮方法: {$ihdr['compression']}\n";
echo "フィルターメソッド: {$ihdr['filter']}\n";
echo "インターレーススキャン: {$ihdr['interlace']}\n";
?>

3.キー関数の説明

unpack()

Unpack()は、バイナリデータをPHPアレイに解析するために使用されます。フォーマット文字列を使用して、各フィールドのタイプと順序を記述します。例えば:

 unpack("Nlength/A4type", $binary);
  • nlengthとは、長さという名前の大規模なエンディアンの無署名の長い整数(4バイト)を読むことを意味します

  • a4typeとは、の固定長(4バイト)のASCII文字列を読むことを意味します。

パック()

代わりに、 pack()は変数をバイナリ形式にパッケージ化できます。たとえば、PNGファイルヘッダーをパッケージ化する場合、以下を使用できます。

 $signature = pack("C8", 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A);

これは、PNGファイルの生成をカスタマイズするときに非常に便利です。

4。高度な分析

後続のPNGブロック(IDAT、IENDなどなど)を解析し続けるには、次のように各ブロックをループするだけです。

  1. 8バイトを読む:4バイトの長さ + 4バイトタイプ

  2. 長さに応じて対応するデータフィールドを読み取ります

  3. 4バイトCRCチェックをスキップします

  4. Iendが遭遇するまで次のブロックを読み続けます

この分析方法は、透明度(TRNS)、カラーパレット(PLTE)、その他のブロックなど、より複雑なPNG特性にも適用できます。

V.結論

PHPのunpack()およびpack()関数を使用することにより、PNGファイルを低レベルで簡単に解析し、それらの根底にある構造を理解できます。このスキルは、画像形式の詳細な理解、カスタマイズされた画像処理ツールの作成、または関連するセキュリティツールの開発に非常に役立ちます。これらのスキルを習得することで、毎日のPHP開発により快適になります。