当前位置: 代码迷 >> J2ME >> j2me 在手机上,截屏您的程序
  详细解决方案

j2me 在手机上,截屏您的程序

热度:700   发布时间:2016-04-17 21:17:09.0
j2me 在手机上,截屏你的程序

KJAVA在这里人气不算很旺,不过这磨灭不了我们这群热爱着J2ME开发的人们的激情。

?

关于这个截屏程序,是需要附加到你的项目中的,因为j2me的手机没听说双线程的。

?

此截屏程序的原理:

把缓冲画笔所在的画布img_buffer转成PNG格式保存到指定路径下,image转png需要一些插值加文件头的操作。

?

这段代码网上有,我也是copy过来进行创新的。

?

你需要做的是:

1.在你的canvas里定义截屏类的对象,初始值null。

2.在你的canvas里定义一个boolean变量,初始值true。

3.在你的canvas里的初始化或者构造方法里new 一个截屏类的对象。

4.在你的canvas里run方法里如同下面代码一样改造,repaint()方法就是重绘方法,c就是截屏类的实例,c.save()方法是保存图片的方法。

public void run() {		while (true) {			startTime = System.currentTimeMillis();//			if(b_isPaint)//			{				repaint();	//重绘//			}//			else//			{//				mainForm.paint(gg);//				c.save(img_buffer);	//c是截屏类实例,save方法是保存图片方法,img_buffer是当前缓冲。//				b_isPaint = true;//			}			timeTaken = System.currentTimeMillis() - startTime;			if (timeTaken < 1000 / DefaultProperties.FPS) {				try {					Thread.sleep(1000 / DefaultProperties.FPS - timeTaken);				} catch (Exception e) {					e.printStackTrace();				}			}		}	}

?

5.你想要以何种触发事件触发这个截屏方法,如果想要触摸屏点击触发,参考以下方法。其他触发方法照之改之。

	protected void pointerPressed(int x, int y) {//		if(x < 30 && x > 0 && y < 30 && y > 0)//		{//			b_isPaint = false;//			color = 0;//		}//		if(b_isPaint)			mainForm.pointerPressed(x, y);//程序主触屏事件	}

?

6.在你的程序里添加截屏类(CGAMG.java)? 第45行写你要保存的路径。

import javax.microedition.lcdui.*;import java.io.*;import javax.microedition.io.file.FileConnection;import javax.microedition.io.Connector;public class CGame extends Canvas {	public void paint(Graphics g)	{	}    //Image2Bytes by AnderLu    //生成的byte[]数组可直接用于外部存储为.png格式的图片文件看图软件可直接打开    public static int IDATPOS;    public static int haha = 0;    public static byte[] HEADChunk = {                                     (byte) 0x89, (byte) 0x50,                                     (byte) 0x4E, (byte) 0x47,                                     (byte) 0x0D, (byte) 0x0A,                                     (byte) 0x1A, (byte) 0x0A,    };    public static byte[] tRNSChunk = {                                     (byte) 0x00, (byte) 0x00,                                     (byte) 0x00, (byte) 0x01,                                     (byte) 0x74, (byte) 0x52,                                     (byte) 0x4E, (byte) 0x53,                                     (byte) 0x00,                                     (byte) 0x40, (byte) 0xE6,                                     (byte) 0xD8, (byte) 0x66,    };    public static byte[] IENDChunk = {                                     //PNGIEND                                     (byte) 0x00, (byte) 0x00,                                     (byte) 0x00, (byte) 0x00,                                     (byte) 0x49, (byte) 0x45,                                     (byte) 0x4E, (byte) 0x44,                                     (byte) 0xAE, (byte) 0x42,                                     (byte) 0x60, (byte) 0x82    };    Image img;    public void save(Image im)    {        byte data[] = Image2Bytes(im);        this.img = Image.createImage(data, 0, data.length);                saveFile("file:///E:/jieping/" + haha +".png", data);	//路径,haha变量递增 保存名为1.png,2.png        haha++;    }    /**保存文件     * @path:路径     * @fileData:文件数据     * @return: 0:出现异常,1:保存成功     */    public int saveFile(String path, byte[] fileData) {        FileConnection fc = null;        try {            fc = (FileConnection) Connector.open(path, Connector.READ_WRITE);            if (!fc.exists()) {                fc.create();            }            OutputStream os = fc.openOutputStream();            os.write(fileData);            os.flush();            os.close();            fc.close();            return 1;        } catch (IOException ex) {            ex.printStackTrace();            return 0;        }    }    public byte[] Image2Bytes(Image img) {        try {            int w = img.getWidth();            int h = img.getHeight();            int offset = 0;            byte buffer[] = new byte[(w * 4 + 1) * h + offset];            getImageBufferForImageARGB8888(img, buffer, w, h, offset);            System.gc();            ByteArrayOutputStream baos = new ByteArrayOutputStream();            DataOutputStream dout = new DataOutputStream(baos);            WritePng(dout, w, h, buffer, null, false, offset);            byte[] data = baos.toByteArray();            writeCRC(data, 8); //更新IHDR CRC            writeCRC(data, 33); //更新PLTE CRC            writeCRC(data, IDATPOS); //更新IDAT CRC            buffer = null;            System.gc();            return data;        } catch (IOException ex) {            ex.printStackTrace();            return null;        }    }    public static void writeCRC(byte[] data, int chunkpos) {        int chunklen = ((data[chunkpos] & 0xFF) << 24)                       | ((data[chunkpos + 1] & 0xFF) << 16)                       | ((data[chunkpos + 2] & 0xFF) << 8)                       | (data[chunkpos + 3] & 0xFF);        int sum = CRCChecksum(data, chunkpos + 4, 4 + chunklen) ^ 0xffffffff;        int val = sum;        int pos = chunkpos + 8 + chunklen;        data[pos] = (byte) ((val & 0xFF000000) >> 24);        data[pos + 1] = (byte) ((val & 0xFF0000) >> 16);        data[pos + 2] = (byte) ((val & 0xFF00) >> 8);        data[pos + 3] = (byte) (val & 0xFF);    }    public static int[] crc_table; //CRC 表    public static int CRCChecksum(byte[] buf, int off, int len) {        int c = 0xffffffff;        int n;        if (crc_table == null) {            int mkc;            int mkn, mkk;            crc_table = new int[256];            for (mkn = 0; mkn < 256; mkn++) {                mkc = mkn;                for (mkk = 0; mkk < 8; mkk++) {                    if ((mkc & 1) == 1) {                        mkc = 0xedb88320 ^ (mkc >>> 1);                    } else {                        mkc = mkc >>> 1;                    }                }                crc_table[mkn] = mkc;            }        }        for (n = off; n < len + off; n++) {            c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >>> 8);        }        return c;    }    public static long adler32(long adler, byte[] buf, int index, int len) {        int BASE = 65521;        int NMAX = 5552;        //TODO remove this function at all        if (buf == null) {            return 1L;        }        long s1 = adler & 0xffff;        long s2 = (adler >> 16) & 0xffff;        int k;        while (len > 0) {            k = len < NMAX ? len : NMAX;            len -= k;            while (k >= 16) {                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                s1 += buf[index++] & 0xff;                s2 += s1;                k -= 16;            }            if (k != 0) {                do {                    s1 += buf[index++] & 0xff;                    s2 += s1;                } while (--k != 0);            }            s1 %= BASE;            s2 %= BASE;        }        return (s2 << 16) | s1;    }    public static void WritePng(DataOutputStream output, int width, int height,                                byte[] buffer, byte[] colors,                                boolean Transparent, int offset) throws            IOException {        int adler = (int) adler32(1l, buffer, offset, buffer.length - offset);        byte[] lenNlen = { //压缩块的LEN和NLEN信息                         (byte) 0,                         (byte) 0xfa, (byte) 0x7e,                         (byte) 0x05, (byte) 0x81        };        IDATPOS = 0;        output.write(HEADChunk);        IDATPOS += HEADChunk.length;        //写IHDR        output.writeInt(13); //len        output.writeInt(1229472850); //IHDR type code        output.writeInt(width); //写宽度        output.writeInt(height); //写高度        output.writeByte(8); //1Bitdepth        if (colors == null) {            output.writeByte(6); //2ColorType        } else {            output.writeByte(3); //2ColorType        }        output.writeByte(0); //3CompressionMethod        output.writeByte(0); //4Filter method        output.writeByte(0); //5Interlace method        output.writeInt(0); //写crc        IDATPOS += 25;        //写PLTE        if (colors != null) {            output.writeInt(colors.length); //len            output.writeInt(1347179589); //type code            output.write(colors); //data            output.writeInt(0); //crc            IDATPOS += colors.length + 12;        }        //写TRNS        if (Transparent) {            output.write(tRNSChunk);            IDATPOS += tRNSChunk.length;        }        //写IDAT        byte[] dpixels = buffer;        int bufferlen = dpixels.length - offset;        int blocklen = 32506;        int blocknum = 1;        if ((dpixels.length % blocklen) == 0) {            blocknum = bufferlen / blocklen;        } else {            blocknum = (bufferlen / blocklen) + 1;        }        int IDATChunkLen = (bufferlen + 6 + blocknum * 5);        output.writeInt(IDATChunkLen); //len        output.writeInt(1229209940); //idat type code        output.writeShort((short) 0x78da); //78da        for (int i = 0; i < blocknum; i++) {            int off = i * blocklen;            int len = bufferlen - off;            if (len >= blocklen) {                len = blocklen;                lenNlen[0] = (byte) 0;            } else {                lenNlen[0] = (byte) 1;            }            int msb = (len & 0xff);            int lsb = (len >>> 8);            lenNlen[1] = (byte) msb;            lenNlen[2] = (byte) lsb;            lenNlen[3] = (byte) (msb ^ 0xff);            lenNlen[4] = (byte) (lsb ^ 0xff);            output.write(lenNlen);            output.write(dpixels, off + offset, len);        }        output.writeInt(adler); //IDAT adler        output.writeInt(0); //IDAT crc        output.write(IENDChunk);    }    public static void getImageBufferForImageARGB8888(Image img, byte[] rawByte,            int w, int h, int off) {        int n = off;        int[] raw = new int[w];        for (int j = 0; j < h; j++) {            img.getRGB(raw, 0, w, 0, j, w, 1);            for (int i = 0; i < raw.length; i++) {                int ARGB = raw[i];                int a = (ARGB & 0xff000000) >> 24;                int r = (ARGB & 0xff0000) >> 16;                int g = (ARGB & 0xff00) >> 8;                int b = ARGB & 0xff;                if (i % w == 0) {                    n += 1;                }                rawByte[n] = (byte) r;                rawByte[n + 1] = (byte) g;                rawByte[n + 2] = (byte) b;                rawByte[n + 3] = (byte) a;                n += 4;            }        }        raw = null;        System.gc();    }}

?

注意:截屏命名是以1、2、3、4数字++命名的,如1.png,2.png等等,该程序设计的触发截屏事件是点击屏幕左上角,这个根据具体需要随意改了,并且图片保存命名规则也需要完善下。

?

曾尝试过截屏的时候弄点提示,但这是万万不可的,在屏幕上出现任何提示都将会被截屏记录下来,所以我在写这个功能的时候,很是认真的考虑了截屏的完整性及安全性,只要触发了,程序会自动屏蔽所有操作等待截屏操作结束,结束后恢复,也就是说机器慢的,触发截屏了,你在点或者做其他的程序界面的操作,那都是不可能的,截屏生成保存文件这个过程结束后才可以。

?

附件:截屏类(其实就是把image对象转成png并保存到指定路径的方法)

1 楼 javaichiban 2011-04-14  
好文!!
另外我记得在真彩色png图中,PLTE, tRNS等块应该是可以省略的。