⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pngresource.java

📁 j2me游戏制作中对png图片压缩得源代码
💻 JAVA
字号:
import java.io.IOException;
import java.io.InputStream;

import javax.microedition.lcdui.Image;

/*
 * @(#) PNGResource.java 2006-4-4
 *
 * Copyright 2005-2006 城市边缘工作室.All rights reserved.
 * Use is subject to license term
 */

public class PNGResource {
    // 定义标志PNG文件的标识数据
    private final byte[] MARK_FILE = { (byte) 0x89, (byte) 0x50, (byte) 0x4E,
            (byte) 0x47, (byte) 0x0D, (byte) 0x0A, (byte) 0x1A, (byte) 0x0A };

    // 定义标志PNG文件头的标识数据
    private final byte[] MARK_HEADER = { (byte) 0x49, (byte) 0x48, (byte) 0x44,
            (byte) 0x52 };

    // 定义标志PNG文件调色板的标识数据
    private final byte[] MARK_PALETTE = { (byte) 0x50, (byte) 0x4C,
            (byte) 0x54, (byte) 0x45 };

    // 定义标志PNG文件透明度的标识数据
    private final byte[] MARK_TRANS = { (byte) 0x74, (byte) 0x52, (byte) 0x4E,
            (byte) 0x53 };

    // 定义标志PNG文件数据的标识数据
    private final byte[] MARK_IDAT = { (byte) 0x49, (byte) 0x44, (byte) 0x41,
            (byte) 0x54 };

    // 定义标志PNG文件结束的标识数据
    private final byte[] MARK_END = { (byte) 0x00, (byte) 0x00, (byte) 0x00,
            (byte) 0x00, (byte) 0x49, (byte) 0x45, (byte) 0x4E, (byte) 0x44,
            (byte) 0xAE, (byte) 0x42, (byte) 0x60, (byte) 0x82 };

    // 定义CRC的数据
    private final int[] CRC_TABLE_ = new int[256];

    // 定义PNG文件的输入流
    private InputStream is_ = null;

    // 定义资源文件中PNG文件的数目
    private int file_number_ = 0;

    // 定义当前已经装载范围的开始
    private byte from_ = 0;

    // 定义当前已经装载范围的结束
    private byte to_ = 0;

    // 各个PNG文件在资源文件中的偏移量
    private int[] address_ = null;

    // 定义Image对列主要用于存储PNG文件
    private Image[] images_ = null;

    // 定义资源文件名
    private String file_name_ = null;

    /**
     * PNGResource的构造函数,主要完成crc数据的构造
     * 
     */
    public PNGResource() {
        for (int n = 0, c = 0; n < 256; n++) {
            c = n;
            for (int k = 0; k < 8; k++) {
                c = (((c & 1) == 1)) ? (0xedb88320 ^ (c >>> 1)) : (c >>> 1);
            }
            CRC_TABLE_[n] = c;
        }
    }

    /**
     * 打开PNG资源文件,并检测是否正确和进行定位
     * 
     * @param filename
     * @return
     */
    public int open(String filename) {
        if ((is_ = getClass().getResourceAsStream(filename)) == null) {
            // 资源装载失败返回-1
            return -1;
        }
        file_name_ = filename;
        byte[] file_number = new byte[2];
        boolean succeed = true;
        try {
            is_.read(file_number, 0, 2);
            file_number_ = get_int_from_bytes(file_number);
            System.out.println("file_number = " + file_number_);
            address_ = new int[file_number_ + 1];
            images_ = new Image[file_number_];
            int i, offset = 2;
            for (i = 0; i < file_number_; i++) {
                address_[i] = offset;
                offset += 6;
                is_.skip(6);

                byte[] colors = new byte[2];
                is_.read(colors, 0, 2);
                int skip = get_int_from_bytes(colors) * 3;
                //System.out.println("skip 1 = " + skip);
                offset += 2 + skip;
                is_.skip(skip);

                byte[] trans = new byte[1];
                is_.read(trans, 0, 1);
                offset++;
                if (trans[0] == 1) {
                    byte[] l = new byte[2];
                    is_.read(l, 0, 2);
                    skip = get_int_from_bytes(l);
                    offset += (skip + 2);
                    is_.skip(skip);
                }

                byte[] datas = new byte[1];
                is_.read(datas, 0, 1);
                offset++;
                byte[] d = new byte[4];
                for (int k = 0; k < datas[0]; k++) {
                    is_.read(d, 0, 4);
                    skip = get_int_from_bytes(d);
                    //System.out.println("skip 2 = " + skip);
                    offset += (4 + skip);
                    is_.skip(skip);
                }
            }
            address_[i] = offset;
        } catch (IOException e) {
            e.printStackTrace();
            succeed = false;
        }
        try {
            is_.close();
        } catch (IOException e) {
        }
        is_ = null;
        System.gc();
        return succeed ? 0 : -1;
    }

    /**
     * 从资源文件中开始装在数据,并拼成PNG的Image
     * 
     * @param from
     * @param to
     * @return
     */
    public int loading(byte from, byte to) {
        if (from < 0 || to < 0 || from > file_number_ || to > file_number_
                || from > to) {
            // 输入参数有错误
            return -1;
        }

        if ((is_ = getClass().getResourceAsStream(file_name_)) == null) {
            // 资源装载失败返回-1
            return -1;
        }
        from_ = from;
        to_ = to;
        int offset = 0, len = 0;

        try {
            is_.skip(address_[from_]);
        } catch (IOException e) {
            return -1;
        }
        boolean succeed = true;
        for (int i = from_; i <= to_; i++) {
            // 分配png图片所需的内存资源,因为需要加其他的信息需要多分配点
            int size = address_[i + 1] - address_[i] + 200;
            byte[] buffer = new byte[size];
            System.arraycopy(MARK_FILE, 0, buffer, 0, 8);
            offset = 8;
            //System.out.println("==============================>>>1");
            if ((len = update_header(buffer, offset, is_)) == -1) {
                succeed = false;
                break;
            }
            offset += len;
            //System.out.println("==============================>>>2");

            if ((len = update_palette(buffer, offset, is_)) == -1) {
                succeed = false;
                break;
            }
            offset += len;

            if ((len = update_trans(buffer, offset, is_)) == -1) {
                succeed = false;
                break;
            }
            offset += len;

            //System.out.println("==============================>>>3");

            if ((len = update_idata(buffer, offset, is_)) == -1) {
                succeed = false;
                break;
            }
            offset += len;
            //System.out.println("==============================>>>4");
            System.arraycopy(MARK_END, 0, buffer, offset, 12);
            offset += 12;

            images_[i] = Image.createImage(buffer, 0, offset);
            buffer = null;
            System.gc();
        }

        try {
            is_.close();
        } catch (IOException e) {
        }
        is_ = null;
        System.gc();
        return succeed ? 0 : -1;
    }

    /**
     * 根据索引值获得所需Image的句柄
     * 
     * @param index
     * @return
     */
    public Image create_image(int index) {
        return images_[index];
    }

    /**
     * 释放资源管理器中某一个Image的资源
     * 
     * @param index
     */
    public void release(int index) {

    }

    /**
     * 释放资源管理器中所有的已经已经装在的Image资源
     */
    public void release() {
    }

    /**
     * 从16进制的缓冲区中获得10进制的整数
     * 
     * @param data
     * @return
     */
    private int get_int_from_bytes(byte[] data) {
        if (data.length > 4) {
            return -1;
        }
        int result = 0;
        for (int i = data.length - 1, j = 0; i >= 0; i--, j += 8) {
            result |= (data[i] & 0xFF) << j;
        }
        return result;
    }

    /**
     * 计算缓冲区中的数据的CRC校验码,该函数主要确定需要校验数据的开始位置
     * 和长度,同时需要将校验码放入缓冲区最后的4个字节的位置中
     * 
     * @param data
     * @param offset
     * @param len
     * @return 0 成功 -1 失败
     */
    private int update_crc(byte[] buffer, int offset, int len) {
        if (buffer.length < (offset + len + 4)) {
            // 输入的数据缓冲区不正确
            return -1;
        }

        int c = 0xFFFFFFFF;
        for (int n = offset; n < len + offset; n++) {
            c = CRC_TABLE_[(c ^ buffer[n]) & 0xff] ^ (c >>> 8);
        }
        int result = c ^ 0xFFFFFFFF;
        int crc_offset = offset + len;
        buffer[crc_offset + 0] = (byte) ((result >> 24) & 0xff); //237
        buffer[crc_offset + 1] = (byte) ((result >> 16) & 0xff); //221
        buffer[crc_offset + 2] = (byte) ((result >> 8) & 0xff); //226
        buffer[crc_offset + 3] = (byte) ((result >> 0) & 0xff); //82
        return 0;
    }

    /**
     * 
     * @param buffer
     * @param offset
     * @param length
     * @return
     */
    private int update_length(byte[] buffer, int offset, int length) {
        buffer[offset + 0] = (byte) ((length & 0xff000000) >> 24);
        buffer[offset + 1] = (byte) ((length & 0x00ff0000) >> 16);
        buffer[offset + 2] = (byte) ((length & 0x0000ff00) >> 8);
        buffer[offset + 3] = (byte) ((length & 0x000000ff) >> 0);
        return 4;
    }

    /**
     * 还原PNG文件头的数据
     * 
     * @param buffer
     * @param offset
     * @param is
     * @return
     */
    private int update_header(byte[] buffer, int offset, InputStream is) {
        byte[] buf = new byte[6];
        try {
            is.read(buf);
        } catch (IOException e) {
            return -1;
        }

        update_length(buffer, offset, 13);
        offset += 4;
        int crc_offset = offset;
        System.arraycopy(MARK_HEADER, 0, buffer, offset, 4);
        offset += 4;
        buffer[offset + 2] = buf[0];
        buffer[offset + 3] = buf[1];
        buffer[offset + 6] = buf[2];
        buffer[offset + 7] = buf[3];
        buffer[offset + 8] = buf[4];
        buffer[offset + 9] = buf[5];

        update_crc(buffer, crc_offset, 17);
        return 25;
    }

    /**
     * 还原PNG调色板的数据
     * 
     * @param buffer
     * @param offset
     * @param is
     * @return
     */
    private int update_palette(byte[] buffer, int offset, InputStream is) {
        byte[] buf = new byte[2];
        int colors = 0;
        try {
            is.read(buf);
            colors = get_int_from_bytes(buf) * 3;
            //System.out.println("colors = " + colors);
            buf = new byte[colors];
            is.read(buf);
        } catch (IOException e) {
            return -1;
        }

        update_length(buffer, offset, colors);
        offset += 4;
        int crc_offset = offset;
        System.arraycopy(MARK_PALETTE, 0, buffer, offset, 4);
        offset += 4;
        System.arraycopy(buf, 0, buffer, offset, colors);

        update_crc(buffer, crc_offset, colors + 4);
        return colors + 12;
    }

    private int update_trans(byte[] buffer, int offset, InputStream is) {
        byte[] buf = new byte[1];
        int count = 0;
        //int a = offset; 
        try {
            is.read(buf);
            if (buf[0] == 0) {
                return 0;
            }
            buf = new byte[2];
            is.read(buf);
            count = get_int_from_bytes(buf);
        } catch (IOException e) {
            return -1;
        }
        //System.out.println("count = " + count);
        buffer[offset + 2] = buf[0];
        buffer[offset + 3] = buf[1];
        int crc_offset = offset + 4;
        System.arraycopy(MARK_TRANS, 0, buffer, offset + 4, 4);
        buf = new byte[count];
        try {
            is.read(buf);
        } catch (IOException e) {
            return -1;
        }
        System.arraycopy(buf,0,buffer,offset + 8,count);
        update_crc(buffer, crc_offset, count + 4);
//        for(int i = a ;i < a + count + 12;i++){
//            System.out.print(" " + Integer.toHexString(buffer[i]));
//        }
//        System.out.println();
        return (count + 12);
    }

    /**
     * 还原PNG像素点的数据
     * 
     * @param buffer
     * @param offset
     * @param is
     * @return
     */
    private int update_idata(byte[] buffer, int offset, InputStream is) {
        byte[] buf = new byte[1];
        int chunk = 0;
        try {
            is.read(buf);
            chunk = buf[0];
        } catch (IOException e) {
            return -1;
        }

        int length = 0;
        for (int i = 0; i < chunk; i++) {
            buf = new byte[4];
            int len = 0;
            try {
                is.read(buf);
                len = get_int_from_bytes(buf);
                buf = new byte[len];
                is.read(buf);
            } catch (IOException e) {
                return -1;
            }
            update_length(buffer, offset, len);
            offset += 4;
            int crc_offset = offset;
            System.arraycopy(MARK_IDAT, 0, buffer, offset, 4);
            offset += 4;
            System.arraycopy(buf, 0, buffer, offset, len);
            update_crc(buffer, crc_offset, len + 4);
            offset += (len + 4);
            length += (len + 12);
        }
        return length;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -