2010-02-03 16 views
11

यह वही है मैं अब तक है:मैं PHP से पीएनजी मेटाडाटा कैसे पढ़ सकता हूं?

<?php 

$file = "18201010338AM16390621000846.png"; 

$test = file_get_contents($file, FILE_BINARY); 

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

?> 

उत्पादन sorta है कि मैं क्या चाहता हूँ, लेकिन मैं वास्तव में केवल लाइनों 3-7 (सम्मिलित) की जरूरत है। यह आउटपुट अब जैसा दिखता है: http://silentnoobs.com/pbss/collector/test.php। मैं "पंकबस्टर स्क्रीनशॉट (±) एएओ ब्रिज क्रॉसिंग" से डेटा प्राप्त करने की कोशिश कर रहा हूं "परिणाम: डब्ल्यू = 3 9 4 एक्स एच = 1 9 6 नमूना = 2"। मुझे लगता है कि यह फाइल के माध्यम से पढ़ने के लिए काफी सीधे आगे होगा, और प्रत्येक पंक्ति को सरणी में स्टोर करेगा, लाइन [0] को "पंकबस्टर स्क्रीनशॉट (±) एएओ ब्रिज क्रॉसिंग" और इसी तरह की आवश्यकता होगी। ये सभी पंक्तियां बदल सकती हैं, इसलिए मैं केवल कुछ सीमित नहीं खोज सकता।

मैंने कुछ दिनों के लिए कोशिश की है, और यह बहुत मदद नहीं करता है कि मैं php पर गरीब हूं।

+0

क्षमा करें, न लक्ष्य है और न ही प्रश्न को समझने ... – deceze

+1

पीएनजी मात्रा में बांटा गया है (http://www.libpng.org/pub/png/spec/ 1.2/पीएनजी-Chunks.html)। और आप शायद 'टेक्स्ट' खंड की तलाश में हैं जिसमें एक टिप्पणी है ('टिप्पणी' कीवर्ड के साथ निर्दिष्ट)। – Gumbo

उत्तर

16

PNG file format परिभाषित करता है कि एक पीएनजी दस्तावेज डेटा के कई हिस्सों में विभाजित होता है। इसलिए आपको अपनी इच्छा के अनुसार अपने रास्ते पर नेविगेट करना होगा।

जो डेटा आप निकालना चाहते हैं उसे tEXt खंड में परिभाषित किया गया प्रतीत होता है। मैंने निम्नलिखित वर्ग को लिखा है ताकि आप पीएनजी फाइलों से हिस्सों को निकालने की अनुमति दे सकें।

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

यदि उसे केवल टेक्स्ट भाग की आवश्यकता है, तो यह पूरे पीएनजी डेटा को लोड करने के लिए स्मृति की बर्बादी है (यानी 'फ्रेड' बनाम' fseek')। – Matthew

+0

@ कोंफोर्स: मैंने कक्षाओं को केवल भागों के ऑफसेट स्टोर करने के लिए फिर से पहचाना है। वे एक प्रयोग के आधार पर पढ़ा जाता है। मैं उपर्युक्त वर्ग को बहुमुखी के रूप में यथासंभव रखना चाहता हूं। –

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

यह एक मूल रूप से अच्छी तरह से गठन PNG फ़ाइल मान लिया गया है।

संबंधित मुद्दे