網(wǎng)上許多關(guān)于這個(gè)問題的回答都?xì)w結(jié)為兩個(gè):
- 提供一段不能正確處理多段IDAT情況的代碼抱完,無法處理Xcode7(以前的版本是否同樣刃泡,未考究)打包生成的IPA包里的PNG文件。
- 使用Apple自己的轉(zhuǎn)換命令
xcrun pngcrush -revert-iphone-optimizations
烘贴,這個(gè)命令在Mac上當(dāng)然是好用的,但是老翘,并不能在Linux上使用锻离。
Linux下的pngcrush能識(shí)別IPA格式的PNG圖,然后也并不能正確處理纳账。
最后深挖了一輪之后找到這段實(shí)現(xiàn)。這段實(shí)現(xiàn)和網(wǎng)上流傳的一個(gè)版本的實(shí)現(xiàn)很像永罚,但是能夠正確的處理多段IDAT的情況(原諒我卧秘,找到之后做了一輪測試,無意中關(guān)閉了瀏覽器翅敌,卻再也找不回出處了)
下面的代碼并非我原創(chuàng),有知道原著地址的朋友蚯涮,請幫忙告知一下
def getNormalizedPNG(filename):
pngheader = "\\\\x89PNG\\\\r\\\\n\\\\x1a\\\\n"
file = open(filename, "rb")
oldPNG = file.read()
file.close()
if oldPNG[:8] != pngheader:
return None
newPNG = oldPNG[:8]
chunkPos = len(newPNG)
idatAcc = ""
breakLoop = False
foundCgBI = False
# For each chunk in the PNG file
while chunkPos < len(oldPNG):
skip = False
# Reading chunk
chunkLength = oldPNG[chunkPos:chunkPos+4]
chunkLength = unpack(">L", chunkLength)[0]
chunkType = oldPNG[chunkPos+4 : chunkPos+8]
chunkData = oldPNG[chunkPos+8:chunkPos+8+chunkLength]
chunkCRC = oldPNG[chunkPos+chunkLength+8:chunkPos+chunkLength+12]
chunkCRC = unpack(">L", chunkCRC)[0]
chunkPos += chunkLength + 12
# Parsing the header chunk
if chunkType == "IHDR":
width = unpack(">L", chunkData[0:4])[0]
height = unpack(">L", chunkData[4:8])[0]
# Parsing the image chunk
if chunkType == "IDAT":
# Store the chunk data for later decompression
idatAcc += chunkData
skip = True
# Removing CgBI chunk
if chunkType == "CgBI":
skip = True
foundCgBI = True
# Add all accumulated IDATA chunks
if chunkType == "IEND":
try:
# Uncompressing the image chunk
bufSize = width * height * 4 + height
chunkData = decompress( idatAcc, -15, bufSize)
except Exception, e:
# The PNG image is normalized
print "Decompress exception:%s" % e
return None
chunkType = "IDAT"
# Swapping red & blue bytes for each pixel
newdata = ""
for y in xrange(height):
i = len(newdata)
newdata += chunkData[i]
for x in xrange(width):
i = len(newdata)
newdata += chunkData[i+2]
newdata += chunkData[i+1]
newdata += chunkData[i+0]
newdata += chunkData[i+3]
# Compressing the image chunk
chunkData = newdata
chunkData = compress( chunkData )
chunkLength = len( chunkData )
chunkCRC = crc32(chunkType)
chunkCRC = crc32(chunkData, chunkCRC)
chunkCRC = (chunkCRC + 0x100000000) % 0x100000000
breakLoop = True
if not skip:
newPNG += pack(">L", chunkLength)
newPNG += chunkType
if chunkLength > 0:
newPNG += chunkData
newPNG += pack(">L", chunkCRC)
if breakLoop:
break
if not foundCgBI:
# It shout be not Xcode PNG format
return None
return newPNG```
###然后上面的代碼還是有一些小問題张峰,使用時(shí)候需要注意的:
###它不能正確的判斷文件的格式,一律按IPA的格式處理喘批。當(dāng)原文件并不是IPA的格式的時(shí)候,它會(huì)處理出一個(gè)錯(cuò)誤的文件——而不是報(bào)錯(cuò)退出餐曹。
----
總算到我了的貢獻(xiàn)了:
* 在分析每個(gè)Chunk的時(shí)候記錄一下是否有CgBI類型的Chunk敌厘,如果整個(gè)文件都木有這個(gè)類型的塊,那么我認(rèn)為它肯定不是Xcode處理過的PNG格式额湘,返回None。
這樣基本就沒有出現(xiàn)錯(cuò)誤轉(zhuǎn)換的情況了嗡官。