- 注册时间
- 2010-3-12
- 最后登录
- 2011-11-24
- 在线时间
- 117 小时
- 阅读权限
- 255
- 积分
- 4130
- 帖子
- 134
- 精华
- 0
- UID
- 1
  
|
在电脑上,我们可以很方便的通过键盘的PrintScreen键了截取当前屏幕,使用程序来截取当前屏幕并保存的代码也有很多。但是在手机上,并没有PrintScreen这样的键,还好我们可以使用编程来实现截屏的功能。在实际使用的时候,我们需要将这个程序附加到实际的项目中,因为到现在为止我还没有听说那个j2me手机是双线程的。
工作原理:
把缓冲画笔所在的画布img_buffer转成PNG格式保存到指定路径下,image转png需要一些插值加文件头的操作。
具体实现
下面的代码也是我从网上找来的,并根据自己的需要稍稍修改了一下。
你需要做的是:
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等等,该程序设计的触发截屏事件是点击屏幕左上角,这个根据具体需要随意改了,并且图片保存命名规则也需要完善下。
曾尝试过截屏的时候弄点提示,但这是万万不可的,在屏幕上出现任何提示都将会被截屏记录下来,所以我在写这个功能的时候,很是认真的考虑了截屏的完整性及安全性,只要触发了,程序会自动屏蔽所有操作等待截屏操作结束,结束后恢复,也就是说机器慢的,触发截屏了,你在点或者做其他的程序界面的操作,那都是不可能的,截屏生成保存文件这个过程结束后才可以。
|
|