當前位置: 首頁> 最新文章列表> 使用pack() 創建圖片/音頻元數據頭信息

使用pack() 創建圖片/音頻元數據頭信息

M66 2025-05-29

在處理二進制數據時,PHP 提供了一個非常強大的函數—— pack() 。它可以根據指定的格式將數據打包成二進製字符串,這對於創建圖片、音頻等媒體文件的元數據頭信息非常有用。例如,想要構造一個WAV 音頻文件的頭部信息、或是為一個BMP 圖片生成文件頭, pack()都能勝任。

什麼是pack()

pack()函數的基本語法如下:

 string pack(string $format, mixed ...$values)
  • $format是格式字符串,用於指定每個值應如何轉換為二進制。

  • $values是一個或多個要轉換的值。

常見的格式字符包括:

  • C :無符號字符(8 位)

  • n :無符號短整型(16 位,大端字節序)

  • v :無符號短整型(16 位,小端字節序)

  • N :無符號長整型(32 位,大端)

  • V :無符號長整型(32 位,小端)

  • a :NUL 填充字符串

  • A :空格填充字符串

實例一:創建WAV 音頻文件的頭信息

WAV 文件的文件頭遵循RIFF 格式,一般由44 字節的頭部構成。以下是一個最小的WAV 文件頭構造示例:

 <?php
$sampleRate = 44100;
$bitsPerSample = 16;
$channels = 2;
$dataSize = 100000; // 音頻數據大小,假設為 100000 位元組
$byteRate = $sampleRate * $channels * $bitsPerSample / 8;
$blockAlign = $channels * $bitsPerSample / 8;

// 構造 WAV 文件頭
$header = pack(
    'A4VVA4A4VVvvVVvvA4V',
    'RIFF',                // ChunkID
    36 + $dataSize,        // ChunkSize
    0x45564157,            // Format 'WAVE'
    'fmt ',                // Subchunk1ID
    16,                    // Subchunk1Size (PCM)
    1,                     // AudioFormat (1 = PCM)
    $channels,             // NumChannels
    $sampleRate,           // SampleRate
    $byteRate,             // ByteRate
    $blockAlign,           // BlockAlign
    $bitsPerSample,        // BitsPerSample
    'data',                // Subchunk2ID
    $dataSize              // Subchunk2Size
);

// 輸出為實際文件
file_put_contents('output.wav', $header);
?>

該腳本會創建一個output.wav文件頭,你可以隨後附加實際的音頻數據來生成可播放的WAV 文件。

實例二:構建BMP 圖像的文件頭

BMP 文件同樣使用固定格式的頭部,可以使用pack()構造。

 <?php
$width = 100;
$height = 100;
$bitsPerPixel = 24;
$rowSize = (int)(($bitsPerPixel * $width + 31) / 32) * 4;
$imageSize = $rowSize * $height;
$fileSize = 54 + $imageSize; // 54 位元組的头部 + 圖像數據

$header = pack(
    'A2VvvVVVVvvVVVV',
    'BM',             // Signature
    $fileSize,        // File size
    0,                // Reserved1
    0,                // Reserved2
    54,               // Offset to image data
    40,               // Info header size
    $width,           // Width
    $height,          // Height
    1,                // Planes
    $bitsPerPixel,    // Bits per pixel
    0,                // Compression (none)
    $imageSize,       // Image size
    2835,             // X pixels per meter (72 DPI)
    2835,             // Y pixels per meter (72 DPI)
    0,                // Colors used
    0                 // Important colors
);

// 輸出頭部到文件
file_put_contents('output.bmp', $header);
?>

隨後,你可以填充每行像素數據(注意BMP 的每行需為4 字節對齊)完成圖像文件。

注意事項

  1. 字節序問題:多字節數字要考慮平台端序,使用VN來控制(小端或大端)。

  2. 對齊要求:BMP、WAV 等格式對字段對齊和結構順序有嚴格要求,使用pack()時要確保字段對應準確。

  3. 調試輸出:可以用bin2hex()unpack()來查看打包後的結果是否符合預期。

  4. 構造複雜文件頭:可結合官方格式規範手動解析並轉化為pack()調用。例如要生成一個ID3v2 音頻頭或PNG 的IHDR 塊,務必查閱相關文檔。

結語