Android屏幕截图实现(手记)

/android2.1/system/core/adb/framebuffer_service.c这个里面是DDMS 里面截图通信adbd进程的代码 DDMS那边接到的数据是用JAVA处理的!framebuffer_service.c代码如下:

/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

#include “fdevent.h”
#include “adb.h”

#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

/* TODO:
** – sync with vsync to avoid tearing
*/
/* This version number defines the format of the fbinfo struct.
It must match versioning in ddms where this data is consumed. */
#define DDMS_RAWIMAGE_VERSION 1
struct fbinfo {
unsigned int version;
unsigned int bpp;
unsigned int size;
unsigned int width;
unsigned int height;
unsigned int red_offset;
unsigned int red_length;
unsigned int blue_offset;
unsigned int blue_length;
unsigned int green_offset;
unsigned int green_length;
unsigned int alpha_offset;
unsigned int alpha_length;
} __attribute__((packed));

void framebuffer_service(int fd, void *cookie)
{
struct fb_var_screeninfo vinfo;
int fb, offset;
char x[256];

struct fbinfo fbinfo;
unsigned i, bytespp;

fb = open(“/dev/graphics/fb0″, O_RDONLY);
if(fb < 0) goto done;

if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) goto done;
fcntl(fb, F_SETFD, FD_CLOEXEC);

bytespp = vinfo.bits_per_pixel / 8;

fbinfo.version = DDMS_RAWIMAGE_VERSION;
fbinfo.bpp = vinfo.bits_per_pixel;
fbinfo.size = vinfo.xres * vinfo.yres * bytespp;
fbinfo.width = vinfo.xres;
fbinfo.height = vinfo.yres;
fbinfo.red_offset = vinfo.red.offset;
fbinfo.red_length = vinfo.red.length;
fbinfo.green_offset = vinfo.green.offset;
fbinfo.green_length = vinfo.green.length;
fbinfo.blue_offset = vinfo.blue.offset;
fbinfo.blue_length = vinfo.blue.length;
fbinfo.alpha_offset = vinfo.transp.offset;
fbinfo.alpha_length = vinfo.transp.length;

/* HACK: for several of our 3d cores a specific alignment
* is required so the start of the fb may not be an integer number of lines
* from the base. As a result we are storing the additional offset in
* xoffset. This is not the correct usage for xoffset, it should be added
* to each line, not just once at the beginning */
offset = vinfo.xoffset * bytespp;

offset += vinfo.xres * vinfo.yoffset * bytespp;

if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done;

lseek(fb, offset, SEEK_SET);
for(i = 0; i < fbinfo.size; i += 256) {
if(readx(fb, &x, 256)) goto done;
if(writex(fd, &x, 256)) goto done;
}

if(readx(fb, &x, fbinfo.size % 256)) goto done;
if(writex(fd, &x, fbinfo.size % 256)) goto done;

done:
if(fb >= 0) close(fb);
close(fd);
}

用framebuffer截屏,就是把当前framebuffer的内存dump成bitmap或者压缩成其他图片格式.

在ubuntu下使用命令截屏:

Android G1手机的色深是16bit, 即R/G/B=5/6/6. 故需要一些特殊处理才能获得其屏幕图像。我们可以adb登录进入Android手机,先dump出/dev/fb0的内容,然后将dump出的文件拷贝到PC(ubuntu)上用convert命令进行处理。 1. 在Android手机上获取framebuffer内容: # cat /dev/graphics/fb0 > /mnt/sdcard/fb0 2. 把文件拷贝到PC上的/tmp目录: $ adb pull /mnt/sdcard/fb0 /tmp/fb0 3. 从/tmp/fb0文件中取出第一屏的内容(一般会有2到3屏的内容): $ dd bs=307200 count=1 if=/tmp/fb0 of=/tmp/screenshot1.xmp 这里,手机屏幕分辨率是320*480; 颜色深度为16bit (R/G/B=5/6/5),即2字节; 故有 320*480*2=307200 或在shell下执行: $ echo $((320*480*2)) 这里得到的图像是pixmap格式的. 4. 这时取到的截屏数据要转成每个颜色值为8bit的raw图像数据: 原理如下: int main(int argc, char *argv[]) { unsigned short in; // 16bit unsigned char out[3]; // 8bit*3 while (read(0, &in, 2) == 2) { out[2] = (in & 0x1f) << 3; out[1] = ((in >> 5) & 0x3f) << 2; out[0] = ((in >> 11) & 0x1f) << 3; write(1, out, 3); } return 0; } 将以上代码编译成执行文件/tmp/565to88后,再执行: $ /tmp/565to888 /tmp/screenshot888.xmp 这将把颜色转化为24bit色深。 5.最后把24bit色深的图像转换成PNG格式: $ /usr/bin/convert -depth 8 -size 320×480 rgb:screenshot888.xmp screenshot.png 现在可以用以下命令查看截屏(screenshot.png文件)啦: $ /usr/bin/display screenshot.png


转自:http://www.howandroid.com/2011/07/02/960.html

更多相关文章

  1. android中使用properties文件配置
  2. Android布局文件属性
  3. android从raw里面读取txt文件
  4. android直接找一个文件,部分编译等实用
  5. Android 保存文件路径方法
  6. Android引用百度定位API第三方组件后导致其它.so文件无法正常加
  7. Android上传文件之FTP
  8. Android Studio 如何导入.so文件/jar文件和library库

随机推荐

  1. Android安装APK时出现Local path doesn't
  2. Android中http交互是用HttpUrlConnection
  3. android activity 相互传值
  4. android 控件 3d 旋转效果
  5. Android 创建桌面快捷键
  6. android 按钮的文字显示不全
  7. Android Studio支持Java8方法
  8. 在eclipse中查看Android各版本源代码
  9. Android中使用FFMPEG将yuv420p编码为h264
  10. android 打开摄像头的代码