`
zovikoo
  • 浏览: 11337 次
  • 性别: Icon_minigender_1
  • 来自: 沈阳
最近访客 更多访客>>
社区版块
存档分类
最新评论

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等块应该是可以省略的。

相关推荐

    J2ME模拟器模拟2007版的手机QQ

    J2ME模拟器是为Java Micro Edition(J2ME)应用程序提供的一种软件工具,它能够在个人电脑上运行和测试J2ME应用,而无需实际的移动设备。KEmulator Lite V0.9.8是其中的一款,它是一个功能相对简单但实用的免费J2ME...

    基于J2ME的手机赛车游戏源代码

    J2ME,全称Java 2 Micro Edition,是Java平台的一个子集,用于开发和部署在移动设备、嵌入式设备上的应用程序,如手机、PDA和电视。 【描述】中的内容揭示了此项目的重要价值。对于J2ME爱好者,源代码提供了深入...

    j2me五子棋游戏源码

    通过分析这个五子棋游戏的源码,你可以深入学习J2ME的编程实践,掌握游戏开发的关键技术,并且提升你在移动平台上的软件设计和优化能力。同时,对于想要开发自己移动游戏的开发者,这是一个很好的起点和参考资料。

    j2me手机游戏源代码

    【标题】"j2me手机游戏源代码"指的是基于Java 2 Micro Edition(J2ME)平台开发的手机游戏的原始编程代码。J2ME是Java的一种轻量级版本,主要用于移动设备和嵌入式系统,如早期的智能手机和平板电脑。这个特定的源...

    J2ME开发工具篇.zip

    本资料主要探讨了在诺基亚和摩托罗拉等手机上进行J2ME应用程序开发的两款常用工具,帮助开发者入门并掌握移动应用开发的基础知识。 1. **NetBeans IDE for Java ME** NetBeans IDE是Java开发者广泛使用的集成开发...

    NIIT机考J2ME截图

    J2ME的全称是Java 2 Platform, Micro Edition,它提供了一个灵活的框架,使开发者能够创建能在多种不同硬件和操作系统上运行的跨平台应用。 **NIIT机考与J2ME** NIIT(National Institute of Information ...

    JAVA基于J2ME的手机游戏开发(论文+源代码).rar

    本节是JAVA基于J2ME的手机游戏开发(论文+源代码),希望能对你有所帮助。每到毕业季,很多大四同学苦于没有参考的毕设资料,或者下载的资料不全、代码有问题,数据有问题等等,造成毕设出现问题影响大学毕业。现在,...

    程序设计J2ME补考说明.doc

    程序设计J2ME补考说明主要涉及的知识点集中在Java Micro Edition (J2ME)的程序设计,特别是针对手机应用的开发。J2ME是Java平台的一个子集,用于开发和部署在嵌入式设备,如移动电话、PDA等上的应用程序。在这个补考...

    NIIT机考J2ME截图1

    【标题】"NIIT机考J2ME截图1"揭示了这个压缩包是关于NIIT机构J2ME(Java Micro Edition)课程机考的问题和答案的集合。这可能是一个复习资料,帮助学生准备或者理解考试中的核心概念和技术。 J2ME是Java平台的一个...

    J2ME网络游戏代码

    以上功能,本人在moto e398上测试通过。本游戏产品代码,供有兴趣的入门朋友参考。里面涉及的五子棋算法,经网上单机程序修改而来。 本人qq:376680338 zhengyu_xie@hotmail.com; 二、 环境配置说明 服务端需建立...

    KEmulator v1.0 绿色中文版 PC 平台上强大的手机 J2ME(java)模拟器.zip

    KEmulator 1.0 绿色中文版是目前最为强大的手机J2ME(java)游戏或软件的模拟器, 你可以在电脑上直接运行众多的 JAVA 游戏。KEmulator 1.0 就是这样一个模拟器,它不仅有着速度快,稳定,使用方便等特点,更有许多...

    J2ME中文教程

    在《J2ME中文教程》PDF文档中,读者可以期待找到上述所有主题的详细解释,以及丰富的实例代码和截图,帮助初学者快速上手J2ME开发。对于有志于进入移动开发领域的程序员来说,这是一份非常实用的学习资料。通过学习...

    大学手机课程表程序,可加入多个班级的课程表,十分适合辅导员使用

    1. **跨平台性**:J2ME是一种轻量级的Java平台,适用于资源有限的移动设备,因此这个课程表程序可以在不同品牌和型号的手机上运行。 2. **MIDP与CLDC**:J2ME主要包括两个主要部分,移动信息设备描述(MIDP)和连接...

    今天来上传个不错的J2ME学习教程

    【标题】"今天来上传个不错的J2ME学习教程"所涵盖的知识点主要集中在J2ME(Java 2 Micro Edition)这一移动设备上的Java应用程序开发平台。J2ME是Java平台的一个子集,专为资源有限的嵌入式设备如手机、智能电视和...

    LG手机游戏泡泡堂J2ME源程序

    内容索引:JAVA源码,游戏娱乐,泡泡堂游戏源码 韩国LG手机上的一款J2ME游戏泡泡堂源码,运行截图如下所示,声音需要LG特有的API支持才行,找不到LG手机的SDK,只好建了个空接口,游戏在SJBOY下可以运行,但是没有声音...

    有关手机游戏的一些资源图片

    J2ME是一种轻量级的Java平台,它允许开发者创建能在各种移动设备上运行的应用程序,包括游戏。在J2ME中,游戏通常使用MIDP(Mobile Information Device Profile)和CLDC(Connected Limited Device Configuration)...

    1945飞机战斗游戏J2ME源代码.7z

    通过这些源代码,开发者可以学习到如何在J2ME平台上构建2D游戏,包括: 1. 使用MIDP (Mobile Information Device Profile) API进行图形绘制和用户交互。 2. 实现游戏循环,包括游戏逻辑更新和屏幕重绘。 3. 创建和...

    java源码包---java 源码 大量 实例

    (2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户可以在终端上直接地使用它,但是它的主要作用是供程序使用的。本规范尝试满足...

    功能强大的PC电脑端JAVA手机游戏模拟器KEmulator使用教程.doc

    KEmulator是一款专为PC设计的高级JAVA手机游戏和软件模拟器,它能够让你在计算机上无缝体验J2ME(Java)应用程序。KEmulator以其出色的性能和广泛的游戏兼容性,成为了Java游戏爱好者们的首选工具。这款模拟器不仅...

    JAVA模拟《电脑版》

    标题"JAVA模拟《电脑版》"暗示我们将讨论如何在个人电脑上通过Java模拟器运行J2ME应用程序。在PC上使用Java模拟器,开发者可以测试他们的J2ME应用,而用户则可以体验在非移动设备上运行的Java游戏或应用。 ...

Global site tag (gtag.js) - Google Analytics