2017-04-20 543 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