开发者

How can I read PNG Metadata from PHP?

This is what I have so far:

<?php

$file = "18201010338AM16390621000846.png";

$test = file_get_contents($file, FILE_BINARY);

echo str_replace("\n","<br>",$test);

?>

The output is sorta what I want, but I really only need lines 3-7 (inclusively). This is what the output looks like now: http://silentnoobs.com/pbss/collector/test.php. I am trying to get the data from "PunkBuster Screenshot (±) AAO Bridge Crossing" to "Resulting: w=394 X h=196 samp开发者_运维技巧le=2". I think it'd be fairly straight forward to read through the file, and store each line in an array, line[0] would need to be "PunkBuster Screenshot (±) AAO Bridge Crossing", and so on. All those lines are subject to change, so I can't just search for something finite.

I've tried for a few days now, and it doesn't help much that I'm poor at php.


The PNG file format defines that a PNG document is split up into multiple chunks of data. You must therefore navigate your way to the chunk you desire.

The data you want to extract seem to be defined in a tEXt chunk. I've written the following class to allow you to extract chunks from PNG files.

class PNG_Reader
{
    private $_chunks;
    private $_fp;

    function __construct($file) {
        if (!file_exists($file)) {
            throw new Exception('File does not exist');
        }

        $this->_chunks = array ();

        // Open the file
        $this->_fp = fopen($file, 'r');

        if (!$this->_fp)
            throw new Exception('Unable to open file');

        // Read the magic bytes and verify
        $header = fread($this->_fp, 8);

        if ($header != "\x89PNG\x0d\x0a\x1a\x0a")
            throw new Exception('Is not a valid PNG image');

        // Loop through the chunks. Byte 0-3 is length, Byte 4-7 is type
        $chunkHeader = fread($this->_fp, 8);

        while ($chunkHeader) {
            // Extract length and type from binary data
            $chunk = @unpack('Nsize/a4type', $chunkHeader);

            // Store position into internal array
            if ($this->_chunks[$chunk['type']] === null)
                $this->_chunks[$chunk['type']] = array ();
            $this->_chunks[$chunk['type']][] = array (
                'offset' => ftell($this->_fp),
                'size' => $chunk['size']
            );

            // Skip to next chunk (over body and CRC)
            fseek($this->_fp, $chunk['size'] + 4, SEEK_CUR);

            // Read next chunk header
            $chunkHeader = fread($this->_fp, 8);
        }
    }

    function __destruct() { fclose($this->_fp); }

    // Returns all chunks of said type
    public function get_chunks($type) {
        if ($this->_chunks[$type] === null)
            return null;

        $chunks = array ();

        foreach ($this->_chunks[$type] as $chunk) {
            if ($chunk['size'] > 0) {
                fseek($this->_fp, $chunk['offset'], SEEK_SET);
                $chunks[] = fread($this->_fp, $chunk['size']);
            } else {
                $chunks[] = '';
            }
        }

        return $chunks;
    }
}

You may use it as such to extract your desired tEXt chunk as such:

$file = '18201010338AM16390621000846.png';
$png = new PNG_Reader($file);

$rawTextData = $png->get_chunks('tEXt');

$metadata = array();

foreach($rawTextData as $data) {
   $sections = explode("\0", $data);

   if($sections > 1) {
       $key = array_shift($sections);
       $metadata[$key] = implode("\0", $sections);
   } else {
       $metadata[] = $data;
   }
}


<?php
  $fp = fopen('18201010338AM16390621000846.png', 'rb');
  $sig = fread($fp, 8);
  if ($sig != "\x89PNG\x0d\x0a\x1a\x0a")
  {
    print "Not a PNG image";
    fclose($fp);
    die();
  }

  while (!feof($fp))
  {
    $data = unpack('Nlength/a4type', fread($fp, 8));
    if ($data['type'] == 'IEND') break;

    if ($data['type'] == 'tEXt')
    {
       list($key, $val) = explode("\0", fread($fp, $data['length']));
       echo "<h1>$key</h1>";
       echo nl2br($val);

       fseek($fp, 4, SEEK_CUR);
    }
    else
    {
       fseek($fp, $data['length'] + 4, SEEK_CUR);
    }
  }


  fclose($fp);
?>

It assumes a basically well formed PNG file.


I found this problem a few days ago, so I made a library to extract the metadata (Exif, XMP and GPS) of a PNG in PHP, 100% native, I hope it helps. :) PNGMetadata

How can I read PNG Metadata from PHP?


How about:

http://www.php.net/manual/en/function.getimagesize.php

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜