2010-02-03 13 views
11

Questo è quello che ho finora:Come posso leggere i metadati PNG da PHP?

<?php 

$file = "18201010338AM16390621000846.png"; 

$test = file_get_contents($file, FILE_BINARY); 

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

?> 

L'uscita è sorta quello che voglio, ma ho davvero solo bisogno di linee 3-7 (inclusivamente). Ecco come appare ora l'output: http://silentnoobs.com/pbss/collector/test.php. Sto cercando di ottenere i dati da "Screenshot PunkBuster (±) Crossing Bridge AAO" a "Risultato: w = 394 X h = 196 campione = 2". Penso che sarebbe abbastanza semplice leggere il file e memorizzare ogni riga in un array, la linea [0] dovrebbe essere "PunkBuster Screenshot (±) AAO Bridge Crossing" e così via. Tutte quelle linee sono soggette a modifiche, quindi non posso semplicemente cercare qualcosa di finito.

Ho provato per alcuni giorni, e non aiuta molto che io sia povero di php.

+0

Siamo spiacenti, né comprendere l'obiettivo né la domanda ... – deceze

+1

PNG è diviso in blocchi (http://www.libpng.org/pub/png/spec/ 1.2/PNG-Chunks.html). E probabilmente stai cercando il blocco 'tEXt' che contiene un commento (indicato con la parola chiave' comment'). – Gumbo

risposta

16

Il PNG file format definisce che un documento PNG è suddiviso in più blocchi di dati. Devi quindi orientarti verso il pezzo che desideri.

I dati che si desidera estrarre sembrano essere definiti in un blocco tEXt. Ho scritto la seguente classe per permetterti di estrarre pezzi da file 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; 
    } 
} 

Si può usare come tale per estrarre il vostro desiderato tEXt pezzo in quanto tale:

$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

Se ha solo bisogno di pezzi tEXt, è uno spreco di memoria caricare tutti i dati PNG (ad esempio 'fread' vs' fseek'). – Matthew

+0

@konforce: ho rielaborato la classe per archiviare solo offset di blocchi. Vengono letti su base individuale. Voglio mantenere la classe di cui sopra il più versatile possibile. –

2
<?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); 
?> 

assume un file PNG fondamentalmente ben formato.

Problemi correlati