2017-04-20 60 views
2

某些Mac用戶從我們網站的圖像不會在Safari中顯示,他們會報告看到無圖像或黑色圖像。這裏有一個例子:PNG格式圖像不會在Mac Safari上顯示

http://s3-eu-west-2.amazonaws.com/bp18.boxcleverpress.com/Boxclever_logo_chartreuse.png

我發現是:

  • 圖像顯示在PC
  • 圖像上的一些Mac電腦顯示器(我有一箇舊的一個是OK)
  • iPhone和iPad上的圖像顯示
  • 圖片均爲PNG
  • 我優化了im隨着年齡pngtastic
  • 當圖像被複制到Mac和與Adobe Photoshop中打開他們給出的錯誤:文件格式模塊無法解析該文件
  • 當我試圖在Photoshop Elements中打開Windows上我也pngtastic優化的文件得到這個錯誤
  • 當我試圖在Photoshop中打開Windows上的優化文件出現錯誤IDAT:不正確的數據檢查

我會替換未優化者優化的圖像,但我不知道如果這個問題與pngtastic或Adobe圖像庫或其他東西。

+0

替換解決了問題嗎?我也收到來自Safari用戶的關於沒有看到PNG的投訴,但是這些都是在PHP(標準GD庫)中用'imagecreatetruecolor'創建的,而不是以任何方式進行「優化」。 –

+0

@Marten - 是用未經優化的圖像取代允許它們被查看。我希望花一些時間來進一步研究這個問題,並且將我找到的報告回來。 –

回答

2

問題在於Zopfli.java,通過pngtastic包括在內。

它使用該Java代碼來計算阿德勒-32校驗和:

/** 
* Calculates the adler32 checksum of the data 
*/ 
private static int adler32(byte[] data) { 
    int s1 = 1; 
    int s2 = 1 >> 16; 
    int i = 0; 
    while (i < data.length) { 
     int tick = Math.min(data.length, i + 1024); 
     while (i < tick) { 
      s1 += data[i++]; 
      s2 += s1; 
     } 
     s1 %= 65521; 
     s2 %= 65521; 
    } 

    return (s2 << 16) | s1; 
} 

然而,byte S IN的Java是always signed,所以它可能會返回一些數據輸入錯誤的校驗和值。此外,s1s2的裸露int聲明會導致更多複雜情況。

隨着和(我的C版)相同的代碼和data明確聲明爲signed chars1s2signed int,我得到一個錯誤校驗FFFF9180 - 正是一個在損壞的PNG。

如果我將聲明更改爲使用unsigned charunsigned int,它會再次返回正確的校驗和1BCD6EB2


original C code在zopfli阿德勒-32校驗整個使用unsigned類型,所以它只是Java實現,從這個困擾。

+1

謝謝您的調查!我已將該問題報告給pngtastic項目:https://github.com/depsypher/pngtastic/issues/13 –

+0

感謝您追蹤此問題!基於這些發現,我推出了一個新的pngtastic版本。 – depsypher

1

該問題似乎是由於我使用pngtastic優化的PNG中使用了zopfli壓縮。解決方法是使用不同的pngtastic壓縮選項,然後PNG在Photoshop中可讀。

使用不同的壓縮算法會導致較少的優化。

我不知道爲什麼zopfli壓縮是一個問題,它可能是我的代碼有錯誤(儘管只有zopli選項改變時,相同的代碼才能正常工作),在pngtastic或MacOS中Adobe不支持zopfli。

@ usr2564301已經做了一些調查,看來我的示例圖像中的壓縮數據的Adler-32校驗和不正確。 usr2564301也測試了pngtastic代碼,並發現它產生了正確的校驗和。問題可能在於我如何處理pngtastic中的字節流。

下面的代碼進行使用pngtastic(com.googlecode.pngtastic.core)的PNG優化

public static final String OPT_ZOPFLI = "zopfli"; 
public static final String OPT_DEFAULT = "default"; 
public static final String OPT_IMAGEOPTIM = "imageoptim"; 

private String optimization = OPT_ZOPFLI; 

public void optimizePng(File infile, String out) { 

    final InputStream in; 
    try { 
     in = new BufferedInputStream(new FileInputStream(infile)); 
     final PngImage image = new PngImage(in); 

     // optimize 
     final PngOptimizer optimizer = new PngOptimizer(); 

     optimizer.setCompressor(optimization, 1); 
     final PngImage optimizedImage = optimizer.optimize(image, false, 9); 

     // export the optimized image to a new file 
     final ByteArrayOutputStream optimizedBytes = new ByteArrayOutputStream(); 
     optimizedImage.writeDataOutputStream(optimizedBytes); 
     optimizedImage.export(out, optimizedBytes.toByteArray()); 

     } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 
+1

非常有趣。這些圖像是否通過了「pngcheck」? – usr2564301

+1

好點。這是讓我找到解決方法的線索。當我在文件上運行pngcheck時,出現錯誤:「zlib:inflate error = -3」,它向我建議我嘗試不同的壓縮方式,但我不知道zopfli的問題是什麼,或者爲什麼有些機器或應用程序可以閱讀它。 –

+1

這是值得關注的原因 - 而不僅僅是PNG用戶。據稱:「... Zopfli與gzip,Zip,PNG ...使用的壓縮比特流兼容...」(用更少的話來說:Flate),你的經驗表明它不是。馬克阿德勒是這裏的常客,他可能很感興趣。 – usr2564301