如何从 PHP 读取 PNG 元数据?

发布于 2024-08-19 18:01:38 字数 622 浏览 7 评论 0原文

这就是我到目前为止所得到的:

<?php

$file = "18201010338AM16390621000846.png";

$test = file_get_contents($file, FILE_BINARY);

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

?>

输出是我想要的,但我实际上只需要第 3-7 行(包括)。现在的输出如下所示: http://silentnoobs.com/pbss/collector/test。 php.我试图将数据从“PunkBuster Screenshot (±) AAO Bridge Crossing”获取到“Resulting: w=394 X h=196 Sample=2”。我认为读取文件并将每一行存储在一个数组中是相当直接的,行 [0] 需要是“PunkBuster Screenshot (±) AAO Bridge Crossing”,依此类推。所有这些行都可能发生变化,所以我不能只搜索有限的东西。

我已经尝试了几天了,但对我的 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 sample=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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

最偏执的依靠 2024-08-26 18:01:38

PNG 文件格式 定义将 PNG 文档分割成多个数据块。因此,您必须导航到您想要的块。

您想要提取的数据似乎是在 tEXt 块中定义的。我编写了以下类来允许您从 PNG 文件中提取块。

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;
    }
}

您可以使用它来提取所需的 tEXt 块,如下所示:

$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;
   }
}

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;
   }
}
多孤肩上扛 2024-08-26 18:01:38
<?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);
?>

它假设一个基本格式良好的 PNG 文件。

<?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.

世态炎凉 2024-08-26 18:01:38

几天前我发现了这个问题,所以我制作了一个库来用 PHP 提取 PNG 的元数据(Exif、XMP 和 GPS),100% 原生,我希望它有所帮助。 :) PNGMetadata

在此处输入图像描述

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

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文