由于ios打包的软件ipa包里的图标无法直接在Windows上展示,下面工具可以修复解析
package com.
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.CRC32;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
/**
*
* @author penngo
*
*/
public class PngUtil {
public static final int BUFFERSIZE = 4096;
public static void fixPng(String file, String fixFile) throws Exception {
byte[] png_header = { (byte) 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a,
0x0a }; // PNG
byte[] data_chunk = { 0x49, 0x44, 0x41, 0x54 }; // IDAT
byte[] end_chunk = { 0x49, 0x45, 0x4e, 0x44 }; // IEND
byte[] cgbi_chunk = { 0x43, 0x67, 0x42, 0x49 }; // CgBI
byte[] ihdr_chunk = { 0x49, 0x48, 0x44, 0x52 }; // IHDR
File f = new File(file);
FileInputStream in = new FileInputStream(f);
long size = f.length();
byte[] oldPNG = readBytes(in);
in.close();
byte[] header = substr(oldPNG, 0, 8);
if (toHexString(header).equals(toHexString(png_header)) == false) {
throw new Exception("Not a PNG file!");
}
ByteArrayOutputStream idatAcc = new ByteArrayOutputStream();
ByteArrayOutputStream newPNG = new ByteArrayOutputStream();
newPNG.write(header);
boolean breakLoop = false;
int chunkPos = header.length;
int width = 0;
int height = 0;
while (chunkPos < size) {
boolean skip = false;
byte[] chunkLength = substr(oldPNG, chunkPos, 4);
int sl = byteToInt(chunkLength);
byte[] chunkType = substr(oldPNG, chunkPos + 4, 4);
byte[] chunkData = substr(oldPNG, chunkPos + 8, sl);
chunkPos += sl + 12;
if (toHexString(chunkType).equals(toHexString(ihdr_chunk))) {
width = byteToInt(substr(chunkData, 0, 4));
height = byteToInt(substr(chunkData, 4, 8));
}
if (toHexString(chunkType).equals(toHexString(data_chunk))) {
idatAcc.write(chunkData, 0, chunkData.length);
skip = true;
}
if (toHexString(chunkType).equals(toHexString(cgbi_chunk))) {
skip = true;
}
long crc = 0;
if (toHexString(chunkType).equals(toHexString(end_chunk))) {
try {
chunkData = gzinflate(idatAcc.toByteArray());
} catch (Exception e) {
throw new Exception("normal PNG file, not need to fix");
}
chunkType = data_chunk.clone();
ByteArrayOutputStream newdata = new ByteArrayOutputStream();
for (int y = 0; y < height; y++) {
int i = newdata.size();
newdata.write(chunkData[i]);
for (int x = 0; x < width; x++) {
i = newdata.size();
newdata.write(chunkData[i + 2]);
newdata.write(chunkData[i + 1]);
newdata.write(chunkData[i + 0]);
newdata.write(chunkData[i + 3]);
}
}
chunkData = newdata.toByteArray();
chunkData = gzcompress(chunkData);
sl = chunkData.length;
ByteArrayOutputStream dd2 = new ByteArrayOutputStream();
dd2.write(chunkType);
dd2.write(chunkData);
byte[] dd = dd2.toByteArray();
crc = crc32(dd);
breakLoop = true;
}
if (!skip) {
newPNG.write(intToByte(sl));
newPNG.write(chunkType);
if (sl > 0) {
newPNG.write(chunkData);
}
newPNG.write(intToByte((int) crc));
}
if (breakLoop) {
break;
}
}
idatAcc.close();
FileOutputStream out = new FileOutputStream(fixFile);
out.write(newPNG.toByteArray());
newPNG.close();
out.close();
}
public static void main(String[] args) throws Exception {
System.out.println("===");
String name = "src.png";
String name2 = "new.png";
fixPng(name, name2);
}
public static byte[] longToByte(long number) {
byte[] v = new byte[8];
v[0] = (byte) (number >> 56);
v[1] = (byte) (number >> 48);
v[2] = (byte) (number >> 40);
v[3] = (byte) (number >> 32);
v[4] = (byte) (number >> 24);
v[5] = (byte) (number >> 16);
v[6] = (byte) (number >> 8);
v[7] = (byte) (number >> 0);
return v;
}
public static int byteToInt(byte[] b) {
int mask = 0xff;
int temp = 0;
int n = 0;
for (int i = 0; i < 4; i++) {
n <<= 8;
temp = b[i] & mask;
n |= temp;
}
return n;
}
public static byte[] intToByte(int number) {
byte[] v = new byte[4];
v[0] = (byte) (number >> 24);
v[1] = (byte) (number >> 16);
v[2] = (byte) (number >> 8);
v[3] = (byte) (number >> 0);
return v;
}
public static String toHexString(byte[] b) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < b.length; i++) {
sb.append(Integer.toHexString(b[i] & 0xFF));
}
return sb.toString();
}
public static byte[] gzinflate(byte[] b) throws Exception{
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
InputStream inflInstream = new InflaterInputStream(
new ByteArrayInputStream(b), new Inflater(true));
byte bytes[] = new byte[1024];
while (true) {
int length = inflInstream.read(bytes, 0, 1024);
if (length == -1) {
break;
}
outputStream.write(bytes, 0, length);
}
byte[] array = outputStream.toByteArray();
outputStream.close();
return array;
} catch (Exception e) {
throw e;
// e.printStackTrace();
}
//return null;
}
public static byte[] substr(byte[] b, int start, int length) {
byte[] by = new byte[length];
for (int i = 0; i < length; i++) {
by[i] = b[start + i];
}
return by;
}
public static byte[] gzcompress(byte[] utfEncodedBytes)
throws IllegalArgumentException, IllegalStateException {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DeflaterOutputStream gzipOutputStream = new DeflaterOutputStream(
baos);
gzipOutputStream.write(utfEncodedBytes);
gzipOutputStream.finish();
return baos.toByteArray();
} catch (Exception e) {
throw new IllegalStateException("GZIP compression failed: " + e, e);
}
}
public static long crc32(byte[] b) {
CRC32 crc = new CRC32();
crc.update(b);
return crc.getValue();
}
public static byte[] readBytes(InputStream inputStream) {
byte[] bytes = null;
if (inputStream == null) {
throw new RuntimeException("inputStream is null");
}
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
transfer(inputStream, outputStream);
bytes = outputStream.toByteArray();
outputStream.close();
return bytes;
} catch (IOException ex) {
throw new RuntimeException("couldn't read bytes from inputStream",
ex);
}
}
public static int transfer(InputStream in, OutputStream out) {
int total = 0;
byte[] buffer = new byte[BUFFERSIZE];
try {
int bytesRead = in.read(buffer);
while (bytesRead != -1) {
out.write(buffer, 0, bytesRead);
total += bytesRead;
bytesRead = in.read(buffer);
}
return total;
} catch (IOException ex) {
throw new RuntimeException("couldn't write bytes to output stream",
ex);
}
}
}