When processing binary data, PHP provides a very powerful function - pack() . It can package data into binary strings according to the specified format, which is very useful for creating metadata header information for media files such as pictures, audio, etc. For example, if you want to construct the header information of a WAV audio file, or generate a file header for a BMP image, pack() is competent.
The basic syntax of the pack() function is as follows:
string pack(string $format, mixed ...$values)
$format is a format string that specifies how each value should be converted to binary.
$values is one or more values to be converted.
Common format characters include:
C : Unsigned characters (8 bits)
n : Unsigned short integer (16-bit, big-endian)
v : Unsigned short integer (16-bit, small-endian)
N : Unsigned long integer (32-bit, big endian)
V : Unsigned long (32-bit, small-endian)
a : NUL fills the string
A : Space fills string
The file header of a WAV file follows the RIFF format and is generally composed of a 44-byte header. Here is an example of a minimal WAV file header construction:
<?php
$sampleRate = 44100;
$bitsPerSample = 16;
$channels = 2;
$dataSize = 100000; // Audio data size,Assume 100000 byte
$byteRate = $sampleRate * $channels * $bitsPerSample / 8;
$blockAlign = $channels * $bitsPerSample / 8;
// structure WAV File header
$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
);
// Output as actual file
file_put_contents('output.wav', $header);
?>
The script creates an output.wav file header, which you can then attach the actual audio data to generate a playable WAV file.
BMP files also use fixed format headers, which can be constructed using pack() .
<?php
$width = 100;
$height = 100;
$bitsPerPixel = 24;
$rowSize = (int)(($bitsPerPixel * $width + 31) / 32) * 4;
$imageSize = $rowSize * $height;
$fileSize = 54 + $imageSize; // 54 byte的头部 + Image data
$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
);
// Output header to file
file_put_contents('output.bmp', $header);
?>
Then you can fill in each row of pixel data (note that each row of BMP needs to be 4 bytes aligned) to complete the image file.
Byte order problem : Multi-byte numbers should consider platform end order and use V or N to control (little endian or big endian).
Alignment requirements : BMP, WAV and other formats have strict requirements on field alignment and structural order. When using pack() , you must ensure that the fields correspond to accurate.
Debug output : You can use bin2hex() or unpack() to see if the packaged results meet expectations.
Construct complex file headers : can be manually parsed and converted into pack() calls in combination with official format specifications. For example, to generate an IHDR block of an ID3v2 audio head or PNG, be sure to consult the relevant documents.