2017-09-07 35 views
0

我有一個PNG文件問題。PHP Imagick使每次更改特定二進制文件的PNG文件 - 從相同的圖像文件

當我使用PHP Imagick庫轉換圖像時,每次都會得到不同的二進制集,儘管我多次嘗試使用相同的圖像文件。

當我比較這兩個文件時,結果表明它只有幾個字節是不同的,而其餘的字節完全相同,並且這些字節偏移也都是時間相同的。

我真的不知道怎麼來的這些字節可能是所有的時間不同(好像它存儲時間戳或還有什麼呢?)

這裏是高燃點二進制PNG文件的二進制,有人幫助我要弄清楚究竟發生了什麼這個二進制文件:

enter image description here

我還附上了PNG文件:

enter image description here

謝謝。

+1

在上面一行中,您突出顯示的是'tIME'塊的開始,這應該是最後一次修改時間([請參閱此處的規格](https://www.w3.org/TR/PNG/# 11tIME))。你也可以找到[這個Unix SE問題](https://unix.stackexchange.com/questions/255252/create-the-same-png-with-imagemagick-2-times-binaries-differ)有幫助。 –

+0

@JoshH爲什麼只在Linux操作系統中添加?那麼,如何使用Imagick(PHP)保存PNG時如何排除此塊? – Codemole

+1

由於不同的字節每次都處於已知的偏移量,因此可以選擇添加後處理步驟來清零這些字節? – GeorgeQ

回答

1

PNG文件被「分塊」,這意味着它們具有不同的命名部分來定義不同的數據。在PNG file format specification中,您可以在PNG文件中找到關於tIME塊的信息。

時間塊給出了最後一次圖像修改的時間(不是初始圖像創建時的 時間)。

另一件要注意的規範是,第一個字母是小寫(t),這意味着該塊不是必需的。所以,徹底刪除它應該可以解決你的問題。

我沒有使用Imagick,但通過PHP documentation,它看起來像它提供了一種方法來從創建的PNG文件中刪除tIME塊。 0123'方法可讓您更好地控制Imagick對圖像所做的操作(list of available options)。 png:exclude-chunk選項可能是你正在尋找的。

此代碼未經測試,因爲我目前無法使用Imagick庫訪問服務器。

$im = new Imagick(); 
$im->setOption('png:exclude-chunk', 'tIME'); // comma separated list of chunks 
+0

非常感謝您提供2種解決方案,我爲他們兩個都讚不絕口,並且接受這一點,因爲這樣做很好! – Codemole

1

這很可能是由於圖片的元數據?即文件被修改時的時間戳?

看着突出顯示的行之前的行,我可以看到tIME在那裏,所以它似乎是這種情況。

1

如果你正試圖從那些已經被創建,或者如果你沒有訪問Imagick庫圖像刪除tIME塊,我測試了一些代碼,可以從小型十歲上下的* PNG刪除塊文件。

PNG文件具有specific format

  • PNG簽名[8個字節]
  • 塊數據 - 與IHDR開始並以IEND塊在它們之間的其它的塊結束。每個塊具有以下:
    • 長度[4個字節]
    • 類型[4個字節]
    • 數據[長度字節](可能是空的,如果長度爲0)
    • CRC(循環冗餘碼) [4個字節]

利用這些信息,我們就可以通過塊逐一念給我們找到要刪除的一個。

// read the PNG file's contents into a string 
$str = file_get_contents('hD0aZ.png'); 

// how far into the string we are currently 
$offset = 0; 

// offset for the PNG signature (8 bytes) 
$offset += 8; 

// what we will replace in the original string once it is found 
$timechunk = ''; 

while($offset < strlen($str)){ 
    // get the current chunk information 
    list($length,$chunk,$name) = readchunk(substr($str,$offset)); 
    if($name == 'tIME'){ 
     $timechunk = $chunk; 
     break; 
    } 
    // move to the next chunk 
    $offset += $length; 
} 

header("Content-Type:image/png"); 
print str_replace($timechunk,'',$str); 

function readchunk($str){ 
    $length = hexdec(bin2hex(substr($str,0,4))); 
    // 4 bytes for length, 4 bytes for chunk name, 4 bytes for CRC = 12 bytes 
    return array(
     12+$length,     // total length of chunk 
     substr($str,0,12+$length), // full chunk data 
     substr($str,4,4)   // chunk name 
    ); 
} 

*如果您的PNG文件過大,tIME塊不夠早在字符串中,你可能最終與問題,如果你的$offset嘗試走了過來PHP_INT_MAX。但是,我可以讓這段代碼處理你在問題中提供的圖像。