How can I read PNG Metadata from PHP?

后端 未结 4 2103
一生所求
一生所求 2020-11-27 18:47

This is what I have so far:



        
相关标签:
4条回答
  • 2020-11-27 19:07

    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

    0 讨论(0)
  • 2020-11-27 19:09
    <?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.

    0 讨论(0)
  • 2020-11-27 19:19

    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;
       }
    }
    
    0 讨论(0)
  • 2020-11-27 19:30

    How about:

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

    0 讨论(0)
提交回复
热议问题