AS问题解决系列1—iCCP: Not recognizing known sRGB profile

来源:互联网 发布:淘宝抢购神器 编辑:程序博客网 时间:2024/05/22 12:56
摘要 本文解决了Android Studio 1.2.2下编译期间出现的libpng warning: iCCP: Not recognizing known sRGB profile that has been edited警告问题。

目录[-]

  • 1. 问题描述   
  • 2. PNG文件格式   
  • 2.2 数据块(chunk)
  • 2.2.1 4类关键chunk 
  • 2.2.2 14类辅助chunk
  • 2.2.3 chunk格式
  • 3. libpng   
  • 4. 问题分析与解决
  • 4.1 iCCP chunk分析
  • 4.2 出问题PNG图片iCCP chunk分析
  • 4.3 libpng代码分析
  • 4.4 警告信息分析
  • 4.5 回答第一章节中提出的问题
  • 4.6 问题解决
  • 4.6.1 解决方案1: 删除png图片内嵌的iCCP profile sRGB
  • 4.6.2 解决方案2:  将aRGB转换为sRGB
  • 5. 参考资料   
  • 1. 问题描述   

        在Android Studio 1.2.2下编译期间,出现了下面警告信息:

        ...\res\drawable-hdpi\add_green.png: libpng warning: iCCP: Not recognizing known sRGB profile that has been edited

        baidu和google,有一些网友是非png格式的图片(例如jpg格式等)而错误地采用了png为后缀,也会出现上述告警信息,可参见[7],本文不考虑这些情况。

        其他网友的回答基本上都是:原因是新版本的libpng对关于iCCP采用了更严苛的约束。但是是从哪个libpng版本开始严格检查,主要是检查哪些内容导致的告警信息呢?基本上没有看到答案。

       本文先学习下PNG文件格式,然后了解下libpng, 再来分析和解决这个警告信息。

    2. PNG文件格式   

         [2]是WWW PNG的规范,[3]是通过例子来介绍PNG文件格式中文编写,下面材料主要来自于这两份文档。

         每个PNG文件是由一个PNG标识(signature),后面跟一些数据块(chunk)组成,每个chunk由一个chunk类型来标识其功能。


    2.1 PNG标识(signature

        每个PNG文件的前8个字节总是包含以下值:

    十进制   137 80 78 71 13 10 26 10十六进制  89 50 4E 47 0D 0A 1A 0A

        第一个字节0x89超出了ASCII字符的范围,这是为了避免某些软件将PNG文件当做文本文件来处理

    2.2 数据块(chunk)

        在png规范[2]中总计定义了18种chunk,其中4类chunk是关键数据块(critical chunk),每个PNG文件都必须包含它们,其余14类为辅助数据块(ancillary chunks),这是可选的数据块。

    2.2.1 4类关键chunk 

        IHDR: image header, 在PNG文件中位置为第一块chunk.

        PLTE: 调色板(palette table), 位于IDAT块之前.

        IDAT: 图像数据块, 可以有多个连续的IDAT块.

        IEND: image trailer, 在PNG文件中位置为最后一块chunk.

    2.2.2 14类辅助chunk

       14类辅助chunk可以归类为以下几种:

    a. Transparency information(透明信息) 

        tRNS(Transparency-透明)


    b. Colour space information(颜色空间信息) 

        cHRM(Primary chromaticities and white point:基色与白色点)

        gAMA(Image gamma:图像gamma)

        iCCP(Embedded ICC profile:内嵌ICC profile)

        sBIT(Significant bits:样本有效位)

        sRGB(Standard RGB colour space:标准RGB颜色空间)


    c. Textual information(文本信息)

        iTXt(International textual data: 国际化文本数据) 

        tEXt(Textual data:文本数据)

        zTXt(Compressed textual data: 压缩文本数据)


    d. Miscellaneous information(其他信息)

        bKGD(Background colour:背景颜色)

        hIST(Image histogram:图像直方图)

        pHYs(Physical pixel dimensions:物理像素尺寸)

        sPLT(Suggested palette:建议调色)


    e. Time information(时间信息)

        tIME(Image last-modification time: 图像最后修改时间)

    2.2.3 chunk格式

       每一块chunk由3个或4个字段组成。

       Length (长度)                       4字节    指定Chunk Data字段的长度,可以为0, 不超过(2^31-1)字节  

       Chunk Type(数据块类型)      4字节    数据块类型由ASCII字母(A-Z和a-z)组成, 

                                                    每个字节的bit 5表示chunk属性, 可参见[2]中5.4 Chunk naming conventions

       Chunk Data (数据块数据)     可变长度  存储按照Chunk Type指定的数据  

       CRC (循环冗余检测)               4字节     存储用来检测是否有错误的循环冗余码


       [2]中5.6 Chunk ordering描述了每一类chunk在PNG文件中的顺序。

       

       IEND chunk中没有data字段,因此Length字段为0, IEND chunk为以下12个字节(十六进制): 

       00 00 00 00 49 45 4E 44 AE 42 60 82 

       前4个字节为00 00 00 00,Type总是IEND(49 45 4E 44),因此,CRC码也总是AE 42 60 82,每个PNG文件最后12字节都是相同的。

    3. libpng   

        [4]是libpng官方首页,从介绍中可知道它是用ANSI C (C89)编写,需要zlib 1.0.4/1.2.5及更高版本。当前最新版本是1.6.17(2015-07-16),从1.6源码 http://sourceforge.net/p/libpng/code/ci/libpng16/tree/CHANGES 可看出1.6.18正式版本正即将发布。

        在该官网首页有以下漏洞警告信息:

        libpng versions 1.6.9 through 1.6.15 (and some subset of versions up through 1.5.20) have an integer-overflow vulnerability in png_combine_row() when decoding very wide interlaced images, which can allow an attacker to overwrite an arbitrary amount of memory with arbitrary (attacker-controlled) data. This vulnerability has been assigned ID CVE-2014-9495 and is fixed in versions 1.6.16 and 1.5.21, released on 21 December 2014.

        因此推荐尽可能使用最新版本的linpng。

    4. 问题分析与解决

        前面简要分析了PNG文件格式中的chunk, 以及libpng后,下面就开始分析和解决前面遇到的警告问题:

        ...\res\drawable-hdpi\add_green.png: libpng warning: iCCP: Not recognizing known sRGB profile that has been edited

    4.1 iCCP chunk分析

        还是需要先分析下iCCP chunk, 其chunk type为十六进制的69 43 43 50(iCCP)。参考[2]中11.3.3.3 iCCP Embedded ICC profile, 可以看出,iCCP chunk包含的data字段为:

        Profile name       1-79 bytes (character string)

        Null separator    1 byte (null character)

        Compression method   1 byte

        Compressed profile      n bytes

        

        其中,profile name是大小写敏感的,只能包含可打印拉丁字符与空格(即范围为十进制字符 32-126 与161-255 ), 不允许在前面与后面存在空格,不允许中间有多个连续空格。压缩方法只能取值为0,0表示对zlib数据流采用deflate压缩,接下来是压缩的profile. 

       每个PNG文件中最多只能包含一个内嵌profile, 可通过在iCCP chunk中显式指定或在sRGB chunk中隐含指定。

    4.2 出问题PNG图片iCCP chunk分析

       下面是出问题add_green.png文件中包含的iCCP chunk截图:

        

        iCCP数据块各字段的含义:   

    十六进制值描    述 00 00 0A 4FiCCP数据块的长度,00 00 0A 4F =十进制263969 43 43 50数据块类型标志,69 43 43 50的ASCII值等于iCCP

                                                                       50 68

    6F 74 6F 73 68 6F 70 20 49 43 43 20 70 72 6F 66

    69 6C 65 00

    Profile名称,长度1~79字节,

    以0作为终止符的字符串, 

    ASCII值等于Photoshop ICC profile

    00压缩方法,0表示使用deflate压缩78 DA 9D 53~03 98 F3 FC压缩的profile,解码时使用63 33 2D DBCRC

        因此,这里的iCCP chunk的data字段从0x3D开始,由于长度为0A 4F, 因此data字段范围为0x00 3D~ 0A 8C。

           

    4.3 libpng代码分析

       从 http://sourceforge.net/p/libpng/code/ci/libpng16/tree/  下载代码,可看到告警信息是在int png_compare_ICC_profile_with_sRGB( )函数中出现的:

        通过检查http://sourceforge.net/p/libpng/code/ci/d630301d996b152de09028bb6803c4c136a0e85f/log/?path=%2Fpng.c, 可看到png.c中这个函数是在2012.03.29由 John Bowler新增的,修改注释信息为:

        [libpng16] Recognize known sRGB ICC profiles while reading; prefer writing the iCCP profile over writing the sRGB chunk, controlled by the PNG_sRGB_PROFILE_CHECKS option.

        代码中利用PNG_ICC_CHECKSUM宏来定义数组png_sRGB_checks[]中的一项,每一项的结构字段包括adler crc, length, MD5[4], have_md5, is_broken, intent, 见下图:

       

        PNG_ICC_CHECKSUM宏里后三个参数date, length, file-name只是用于标记。

        // 以下4个ICC sRGB profiles是来自于 www.color.org, 每个都有MD5校验码

        

         下面3个profiles没有明确的MD5校验码,如果匹配空的MD5则用其他字段来尝试匹配并给出警告。下面这些profiles中前两个有一个'cprt' tag, 表示它们是由HP(Hewlett Packard)创建的。

        

        根据png_compare_ICC_profile_with_sRGB( )函数中的逻辑,遍历png_sRGB_checks[]数组,当.md5[4]与profile中的md5值相同,length, intent, adler也相同,但重新计算的crc不等时,就将提示“Not recognizing known sRGB profile that has been edited”警告信息。

        在scripts/pnglibconf.dfa文件中说明了本次修改的意图以及缺省检查级别为2的理由:

        setting sRGB_PROFILE_CHECKS default 2

       详细可参见[5]。

    4.4 警告信息分析

        结合libpng中png.c文件 png_compare_ICC_profile_with_sRGB( )函数可以看出,当profile的许多字段都相同时,如果crc不等则提示“Not recognizing known sRGB profile that has been edited”警告信息。

       前面对出问题add_green.png文件分析可得出iCCP chunk中压缩的profile的最后四个字节是03 98 F3 FC, 对应的就是png_sRGB_checks[]数组中最后一个profile的adler字段:

        PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d,

          PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/,

          "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")

       因此,这张图的iCCP profile file name就是"HP-Microsoft sRGB v2 media-relative"。

     

        从https://github.com/madler/zlib/blob/master/zlib.h 中struct z_stream可以看出:

       uLong   adler;      /* adler32 value of the uncompressed data */

       字段adler就是未压缩数据的adler值。那么这个adler字段是做什么用的呢?根据[6], Adler-32校验和在zlib中作为CRC32几乎是可靠的,但是计算起来更快,将iCCP profile data压缩后就追加在data后面。adler其实就是创始人Mark Adler的名字。

    4.5 回答第一章节中提出的问题

        综上,通过对PNG文件格式中iCCP chunk中profile的分析,libpng中png.c文件的分析,www.color.org中ICC sRGB profiles的说明,以及对zlib.h中adler32的分析,可以得出以下结论:

        当PNG图片中iCCP chunk中压缩的profile在处理时,当md5, length, intent, adler32等字段相同,但重新计算的crc不等时则提示“Not recognizing known sRGB profile that has been edited”警告信息。

        上述警告信息在2012.03.29由 John Bowler新增的png_compare_ICC_profile_with_sRGB( )函数在检查时给出,即libpng 1.6.0正式版本中引入这个检查函数。

    4.6 问题解决

         明确了linpng严格检查的版本以及检查的内容后,那么如何来解决该问题呢。

    4.6.1 解决方案1: 删除png图片内嵌的iCCP profile sRGB

        [13, 16, 17]中有一些答案建议通过Image Magick/mogrify/GIMP/exiftool等工具来"convert"或"mogrify"图片,删除png图片中内嵌的iCCP profile sRGB:

       Image Magick使用举例:

           删除单个png文件内的profile:  % convert -strip <input filename> <output filename>

           批量删除所有png文件内的profile sRGB:

               set fn=E:\Program Files\ImageMagick-6.9.0-Q16\convert.exe

               for /f "tokens=*" %%i in ('dir/s/b *.png') do "%fn%" "%%i" -strip "%%i"

       mogrify使用举例:

           删除单个png文件内的profile sRGB:  mogrify +profile sRGB <png file>

          批量删除所有png文件内的profile sRGB:

                 find <path to res folder> -name *.png -exec mogrify +profile sRGB {}  \;

        GIMP使用举例:

           删除内嵌profile, 可先进入Image > Mode > Assign Color Profile并设置为RGB workspace(sRGB built-in), 然后File > Overwrite add_green.png覆盖原来的png文件。

           修改内嵌profile, 可进入Image > Mode > Convert to Color Profile, 可选择一种profile。


       [17]也还提到:libpng 1.6+更严格的检查会对original HP/MS sRGB profile报警。老的profile使用D50 whitepoint, 而D65才是标准。这种profile由Adobe Photoshop使用, 虽然缺省在png图片中并不嵌入该profile。最简单的方法是从图片中删除内嵌的profile,但这会导致颜色有稍许偏差(当有颜色校正系统时)。但如果不希望颜色有偏差(例如用于打印输出), 可以嵌入另一种不同的颜色profile。

       [13]中也有网友指出:这样删除png图片中的iCCP profile sRGB, 将丢失如何来render图片等信息,png中的色彩可能被改变。

    4.6.2 解决方案2:  将aRGB转换为sRGB

       [14]中有网友提到:这个图片是sRGB的改成ARGB(Adobe RGB)的就可以啦,在Android  Studio中的右上角会显示24位而ARGB的图片显示是32位,但我本地报这种警告的png图片除了有32位以外还有24位的,因此这个方案不太可行。

      综合上面的意见,[17]中给出的结论比较令人信服,利用GIMP工具删除内嵌的profile后问题解决。

    5. 参考资料   

    [1] Libpng 1.6.17 - March 26, 2015, http://www.libpng.org/pub/png/src/libpng-1.6.17-README.txt

    [2] Portable Network Graphics (PNG) Specification (Second Edition), http://www.w3.org/TR/2003/PR-PNG-20030520/

    [3] PNG文件结构分析, http://wenku.baidu.com/view/b87e978583d049649b66586a.html?re=view

    [4] libpng官方, http://libmng.com/pub/png/libpng.html

    [5] [libpng16] Recognize known sRGB ICC profiles while reading, http://sourceforge.net/p/libpng/code/ci/921648a997e733eb63e18e835a9b98a5507da197/

    [6] zlib库剖析(1):实现概览, http://blog.csdn.net/zhoudaxia/article/details/8034606

    [7] 图片资源添加出现问题: No resource found that matches the given name 安卓 maven编译, http://1985wanggang.blog.163.com/blog/static/77638332015011114647601/

    [8] zlib Technical Details, http://www.zlib.net/zlib_tech.html

    [9] 漫谈显示器色彩管理(一), http://zhuanlan.zhihu.com/hardware/19648994

    [10] 漫谈显示器色彩管理(二), http://zhuanlan.zhihu.com/hardware/19649559

    [11] 漫谈显示器色彩管理(三), http://zhuanlan.zhihu.com/hardware/19649897

    [12] 漫谈显示器色彩管理(四), http://zhuanlan.zhihu.com/hardware/19651812

    [13] Issue 77704: Built tools 21.0.1: multiple libpng warnings, https://code.google.com/p/android/issues/detail?id=77704

    [14] AndroidStudio中\com.android.support错误如何解决, http://ask.csdn.net/questions/161424

    [15] sRGB与aRGB的颜色设置转换, http://blog.sina.com.cn/s/blog_6cf45fc10102v81s.html

    [[16] libpng warning: iCCP: Not recognizing known sRGB profile that has been edited, https://groups.google.com/forum/#!msg/adt-dev/rjTQ_STR3OE/-UcNQRISTKsJ

    [17] libpng errors, https://wiki.archlinux.org/index.php/Libpng_errors

    [18] GIMP, http://www.gimp.org/

    分享到:  6
    声明:OSCHINA 博客文章版权属于作者,受法律保护。未经作者同意不得转载。
    最新热门职位
    更多开发者职位上 开源中国·招聘
    • java高手 武汉乐易
      月薪: 5-10K
    • 卓盟科技诚聘Android系... 卓盟科技
      月薪: 15-30K
    • Java高级工程师/架构师... 日立咨询
      月薪: 15-30K
    • 测试工程师 旷视科技Megavii(F...
      月薪: 10-15K

    评论5

    • 1楼:绯若虚无 发表于 2015-09-23 11:22 回复此评论
      83
    • 2楼:mgic 发表于 2015-11-18 13:39 回复此评论
      先顶一个,再来看
    • 3楼:新年 发表于 2015-12-28 11:12 回复此评论
      好吧,顶一个
    • 4楼:javakam 发表于 2016-03-04 12:57 回复此评论
      在build.gradle里添加以下两句:aaptOptions.cruncherEnabled = false aaptOptions.useNewCruncher = false,就直接添加到buildToolsVersion的下方即可,然后你再看是不是好了!!!!
      这个是用来关闭Android Studio的PNG合法性检查的,直接不让它检查!!!大家可以试试,我的成功了……(源:CSDN)
    • 5楼:zhao_xiaolu 发表于 2016-03-14 15:00 回复此评论

      引用来自“javakam”的评论

      在build.gradle里添加以下两句:aaptOptions.cruncherEnabled = false aaptOptions.useNewCruncher = false,就直接添加到buildToolsVersion的下方即可,然后你再看是不是好了!!!!
      这个是用来关闭Android Studio的PNG合法性检查的,直接不让它检查!!!大家可以试试,我的成功了……(源:CSDN)
      没有cruncherEnabled啊
    0 0