[还原修复png]解决ipa导出的png无法在windows 下查看的工具

由于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);
        }
    }
 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值