http://code.google.com/p/android-screenshot-library/
代码如下
main.c
- #include <stdlib.h>
-
#include <stdio.h>
-
#include <string.h>
-
-
#include <errno.h>
-
#include <signal.h>
-
#include <sys/types.h>
-
#include <sys/socket.h>
-
#include <netinet/in.h>
-
#include <arpa/inet.h>
-
-
#define _GNU_SOURCE
-
#include <getopt.h>
-
-
#include "common.h"
-
-
#define PORT 42380
-
#define BUF_SIZE 256
-
#define SCREENSHOT_CMD "SCREEN"
-
-
#ifdef DEBUG
-
FILE* logFile;
-
#endif
-
-
-
inline void Log(const char* msg)
-
{
-
#ifdef DEBUG
-
if (errno != 0 && logFile == stderr)
-
{
-
char buf[BUF_SIZE];
-
snprintf (buf, BUF_SIZE, "%s (errno=%d)", msg, errno);
-
perror (buf);
-
exit (1);
-
}
-
else fprintf(logFile, "%s\n", msg);
-
fflush (logFile);
-
#endif
-
}
-
-
-
volatile sig_atomic_t end = 0;
-
void sig_INT(int sig) { fprintf(logFile, "------ Caught signal %d -----\n", sig); if (sig == SIGINT || sig == SIGSEGV) end = 1; }
-
-
-
ssize_t Receive(int sfd, char* buf, size_t count, int flags)
-
{
-
int c;
-
size_t len = 0;
-
-
do
-
{
-
c = recv(sfd, buf, count, flags);
-
if (c < 0) return c;
-
if (c == 0) return len;
-
-
buf += c;
-
len += c;
-
count -= c;
-
} while (count > 0);
-
-
return len;
-
}
-
-
ssize_t Send(int sfd, const char* buf, ssize_t count, int flags)
-
{
-
int c;
-
size_t len = 0;
-
-
do
-
{
-
c = send(sfd, buf, count, flags);
-
if (c < 0) return c;
-
-
buf += c;
-
len += c;
-
count -= c;
-
-
//#ifdef DEBUG
-
// char msg[BUF_SIZE];
-
// snprintf (msg, BUF_SIZE, "-- Sent %d bytes (%d total, %d remaining)", c, len, count);
-
// Log (msg);
-
//#endif
-
} while (count > 0);
-
-
return len;
-
}
-
-
-
int start_server()
-
{
-
Log("Starting server...");
-
int sfd = socket(AF_INET, SOCK_STREAM, 0);
-
if (sfd < 0) return -1;
-
Log("- Socket creation");
-
-
struct sockaddr_in sin;
-
sin.sin_family = PF_INET;
-
sin.sin_port = htons(PORT);
-
sin.sin_addr.s_addr = htonl(INADDR_ANY);
-
if (bind (sfd, (struct sockaddr*)&sin, sizeof(struct sockaddr_in)) < 0)
-
return -1;
-
Log("- Socket binding");
-
-
if (listen (sfd, 5) < 0) return -1;
-
Log ("- Socket in listening mode");
-
struct linger l = { 0, 0 };
-
if (setsockopt(sfd, SOL_SOCKET, SO_LINGER, (const void*)&l, sizeof(struct linger)) < 0)
-
return -1;
-
Log("Server started.");
-
-
// get local address and display it
-
#if DEBUG
-
socklen_t sin_len = sizeof(struct sockaddr_in);
-
getsockname (sfd, (struct sockaddr*)&sin, &sin_len);
-
char msg[BUF_SIZE];
-
snprintf (msg, BUF_SIZE, "Listening on %s:%d", inet_ntoa(sin.sin_addr), PORT);
-
Log (msg);
-
#endif
-
-
return sfd;
-
}
-
-
int setup_signals()
-
{
-
Log("Signal handling setup");
-
-
struct sigaction sa;
-
-
// // handle SIGINT
-
// sa.sa_handler = sig_INT;
-
// sigemptyset (&sa.sa_mask);
-
// sa.sa_flags = 0;
-
// if (sigaction(SIGINT, &sa, NULL) < 0) return -1;
-
//
-
// // ignore SIGHUP
-
// sa.sa_handler = SIG_IGN;
-
// sigemptyset (&sa.sa_mask);
-
// sa.sa_flags = 0;
-
// if (sigaction(SIGHUP, &sa, NULL) < 0) return -1;
-
-
int i;
-
for (i = 1; i < 30; ++i) {
-
sa.sa_handler = sig_INT;
-
sigemptyset (&sa.sa_mask);
-
sa.sa_flags = 0;
-
sigaction(i, &sa, NULL);
-
}
-
errno = 0;
-
-
return 0;
-
}
-
-
int accept_client(int servfd, int** client_fd, int* client_count)
-
{
-
Log ("Incoming client connection");
-
-
int cfd = accept(servfd, NULL, NULL);
-
if (cfd < 0) return -1;
-
Log ("- Connection accepted");
-
-
/* check whether the client comes from local system; detach if not */
-
struct sockaddr_in client_addr;
-
socklen_t ca_len = sizeof(struct sockaddr_in);
-
if (getpeername(cfd, (struct sockaddr*)&client_addr, &ca_len) < 0) return -1;
-
if (strcmp(inet_ntoa(client_addr.sin_addr), "127.0.0.1") != 0) {
-
Log ("- Remote client detected -- closing connection.");
-
shutdown (cfd, SHUT_RDWR);
-
close (cfd);
-
return 0;
-
}
-
-
*client_fd = (int*)realloc(*client_fd, sizeof(int) * (*client_count + 1));
-
(*client_fd)[(*client_count)++] = cfd; // (*client_fd)[...] != *client_fd[...] -- f'kin precedence ;/
-
-
return cfd;
-
}
-
-
int handle_client_input(int cfd, char* fddev)
-
{
-
Log ("Client socket signaled for input");
-
struct picture pict;
-
char buf[BUF_SIZE];
-
int c;
-
-
/* read input and parse it */
-
Log ("- Retreiving data");
-
c = Receive(cfd, buf, strlen(SCREENSHOT_CMD), 0);
-
if (c == 0 || (c < 0 && errno == EINTR)) return 0;
-
if (c < 0) return -1;
-
if (c >= strlen(SCREENSHOT_CMD) && (buf[strlen(SCREENSHOT_CMD)] = '\0', strcmp(buf, SCREENSHOT_CMD) == 0))
-
{
-
Log ("- Command identified as " SCREENSHOT_CMD);
-
-
/* screenshot command read; take screenshot and post it through socket */
-
Log ("- Taking screenshot");
-
if (TakeScreenshot(fddev, &pict) < 0) return -1;
-
Log ("- Screenshot taken");
-
-
/* header: width height BPP */
-
memset (buf, 0, BUF_SIZE * sizeof(char));
-
snprintf (buf, BUF_SIZE, "%d %d %d", pict.xres, pict.yres, pict.bps);
-
if (Send(cfd, buf, (strlen(buf) + 1) * sizeof(char), 0) < 0) /* incl. \0 */
-
return -1;
-
Log (buf);
-
Log ("- Response header sent.");
-
-
/* content */
-
if (Send(cfd, pict.buffer, pict.xres * pict.yres * pict.bps / 8, 0) < 0)
-
return -1;
-
Log ("- Screenshot sent");
-
}
-
-
return c;
-
}
-
-
int cleanup(int servfd, int* client_fd, int client_count)
-
{
-
Log ("Shutdown");
-
int i;
-
for (i = 0; i < client_count; ++i)
-
if (close(client_fd[i]) < 0) return -1;
-
free (client_fd);
-
-
Log ("- Closing server socket");
-
if (close(servfd) < 0) return -1;
-
-
Log ("Shutdown complete");
-
-
#ifdef DEBUG
-
if (logFile != stderr) fclose (logFile);
-
#endif
-
return 0;
-
}
-
-
int do_work(int servfd, char* fbDevice)
-
{
-
int* client_fd = NULL;
-
int client_count = 0;
-
int max_fd;
-
fd_set readfs;
-
int i, c;
-
-
Log ("Starting main loop.");
-
while (!end)
-
{
-
/* fill fd_set to check sockets for reading (client and server ones) */
-
Log ("<< select() on sockets... >>");
-
FD_ZERO(&readfs); max_fd = 0;
-
FD_SET(servfd, &readfs);
-
if (servfd > max_fd) max_fd = servfd;
-
for (i = 0; i < client_count; ++i)
-
{
-
if (client_fd[i] < 0) continue;
-
-
FD_SET (client_fd[i], &readfs);
-
if (client_fd[i] > max_fd) max_fd = client_fd[i];
-
}
-
-
if (select(max_fd + 1, &readfs, NULL, NULL, NULL) == -1)
-
{
-
if (errno == EINTR) { errno = 0; continue; }
-
return -1;
-
}
-
-
/* check for input on client socket and handle it */
-
for (i = 0; i < client_count; ++i)
-
{
-
if (client_fd[i] < 0) continue;
-
if (FD_ISSET(client_fd[i], &readfs))
-
{
-
c = handle_client_input (client_fd[i], fbDevice);
-
if (c < 0 && errno != EPIPE && ECONNRESET) return -1;
-
-
/* connection finished */
-
close (client_fd[i]);
-
client_fd[i] = -1; // no socket
-
}
-
}
-
-
/* check whether we have incoming connection */
-
if (FD_ISSET(servfd, &readfs))
-
if (accept_client (servfd, &client_fd, &client_count) < 0)
-
return -1;
-
}
-
Log ("- Caught SIGINT");
-
-
return cleanup(servfd, client_fd, client_count);
-
}
-
-
-
int main(int argc, char* argv [])
-
{
-
#ifdef DEBUG
-
// optional logging to file
-
if (argc >= 2) {
-
logFile = fopen(argv[1], "a+");
-
}
-
else
-
logFile = stderr;
-
#endif
-
Log ("Program initialized");
-
-
char* device;
-
device = "/dev/graphics/fb0";
-
-
int server_socket = start_server();
-
if (server_socket < 0)
-
Log ("Error while starting server");
-
if (setup_signals() < 0)
-
Log ("Error while setting up signals");
-
-
// Log ("Going into background -- have nice day.");
-
// if (setsid () < 0) Log("Error while going into background");
-
if (do_work (server_socket, device) < 0)
-
Log ("Error in main loop");
-
}
fbshot.c
- /*
-
* fbshot.c -- FrameBuffer Screen Capture Utility
-
* (C)opyright 2002 sfires@sfires.net
-
*
-
* Originally Written by: Stephan Beyer
-
* Further changes by: Paul Mundt
-
* Rewriten and maintained by: Dariusz Swiderski
-
* Modular version by: Karol Kuczmarski
-
*
-
* This is a simple program that generates a
-
* screenshot of the specified framebuffer device and
-
* terminal and writes it to a specified file using
-
* the PNG format.
-
*
-
* See ChangeLog for modifications, CREDITS for credits.
-
*
-
* fbshot is free software; you can redistribute it and/or
-
* modify it under the terms of the GNU General Public License
-
* as published by the Free Software Foundation; either Version 2
-
* of the License, or (at your option) any later version.
-
*
-
* fbshot is distributed in the hope that it will be useful, but
-
* WITHOUT ANY WARRANTY; without even the implied warranty of
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-
* GNU General Public License for more details.
-
*
-
* You should have received a copy of the GNU General Public
-
* License with fbshot; if not, please write to the Free Software
-
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-
* 02111-1307 USA
-
*/
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <stdarg.h>
-
#include <string.h>
-
#include <unistd.h>
-
#include <getopt.h>
-
#include <fcntl.h>
-
#include <byteswap.h>
-
#include <sys/types.h>
-
#include <asm/types.h>
-
#include <sys/stat.h>
-
#include <sys/ioctl.h>
-
#include <mntent.h>
-
#include <errno.h>
-
#include <sys/utsname.h>
-
-
#include <sys/vt.h>
-
#include <linux/fb.h>
-
-
#include "common.h"
-
-
#define DEFAULT_FB "/dev/fb0"
-
#define PACKAGE "fbshot"
-
#define VERSION "0.3.1"
-
#define MAINTAINER_NAME "Dariusz Swiderski"
-
#define MAINTAINER_ADDR "sfires@sfires.net"
-
-
static int waitbfg=0; /* wait before grabbing (for -C )... */
-
-
-
/* some conversion macros */
-
#define RED565(x) ((((x) >> (11 )) & 0x1f) << 3)
-
#define GREEN565(x) ((((x) >> (5 )) & 0x3f) << 2)
-
#define BLUE565(x) ((((x) >> (0)) & 0x1f) << 3)
-
-
#define ALPHA1555(x) ((((x) >> (15)) & 0x1 ) << 0)
-
#define RED1555(x) ((((x) >> (10)) & 0x1f) << 3)
-
#define GREEN1555(x) ((((x) >> (5 )) & 0x1f) << 3)
-
#define BLUE1555(x) ((((x) >> (0 )) & 0x1f) << 3)
-
-
void FatalError(char* err){
-
fprintf(stderr,"An error occured: %s %s\nExiting now...\n",err,strerror(errno));
-
fflush(stderr);
-
exit (1);
-
}
-
-
void Usage(char *binary){
-
printf("Usage: %s [-ghi] [-{C|c} vt] [-d dev] [-s n] filename.png\n", binary);
-
}
-
-
void Help(char *binary){
-
printf("FBShot - makes screenshots from framebuffer, v%s\n", VERSION);
-
printf("\t\tby Dariusz Swiderski \n\n");
-
-
Usage(binary);
-
-
printf("\nPossible options:\n");
-
printf("\t-C n \tgrab from console n, for slower framebuffers\n");
-
printf("\t-c n \tgrab from console n\n");
-
printf("\t-d dev\tuse framebuffer device dev instead of default\n");
-
/* not supported as for now
-
printf("\t-g \tsave a grayscaled PNG\n");
-
*/
-
printf("\t-h \tprint this usage information\n");
-
printf("\t-i \tturns OFF interlacing\n");
-
printf("\t-s n \tsleep n seconds before making screenshot\n");
-
-
printf("\nSend feedback !!!\n");
-
}
-
-
void chvt(int num){
-
int fd;
-
if(!(fd = open("/dev/console", O_RDWR)))
-
FatalError("cannot open /dev/console");
-
if (ioctl(fd, VT_ACTIVATE, num))
-
FatalError("ioctl VT_ACTIVATE ");
-
if (ioctl(fd, VT_WAITACTIVE, num))
-
FatalError("ioctl VT_WAITACTIVE");
-
close(fd);
-
if (waitbfg)
-
sleep (3);
-
}
-
-
unsigned int create_bitmask(struct fb_bitfield* bf) {
-
-
return ~(~0u << bf->length) << bf->offset;
-
}
-
-
// Unifies the picture's pixel format to be 32-bit ARGB
-
void unify(struct picture *pict, struct fb_var_screeninfo *fb_varinfo) {
-
-
__u32 red_mask, green_mask, blue_mask;
-
__u32 c;
-
__u32 r, g, b;
-
__u32* out;
-
int i, j = 0, bytes_pp;
-
-
// build masks for extracting colour bits
-
red_mask = create_bitmask(&fb_varinfo->red);
-
green_mask = create_bitmask(&fb_varinfo->green);
-
blue_mask = create_bitmask(&fb_varinfo->blue);
-
-
// go through the image and put the bits in place
-
out = (__u32*)malloc(pict->xres * pict->yres * sizeof(__u32));
-
bytes_pp = pict->bps >> 3;
-
for (i = 0; i < pict->xres * pict->yres * bytes_pp; i += bytes_pp) {
-
-
memcpy (((char*)&c) + (sizeof(__u32) - bytes_pp), pict->buffer + i, bytes_pp);
-
-
// get the colors
-
r = ((c & red_mask) >> fb_varinfo->red.offset) & ~(~0u << fb_varinfo->red.length);
-
g = ((c & green_mask) >> fb_varinfo->green.offset) & ~(~0u << fb_varinfo->green.length);
-
b = ((c & blue_mask) >> fb_varinfo->blue.offset) & ~(~0u << fb_varinfo->blue.length);
-
-
// format the new pixel
-
out[j++] = (0xFF << 24) | (b << 16) | (g << 8) | r;
-
}
-
-
pict->buffer = (char*)out;
-
pict->bps = 32;
-
}
-
-
-
int read_fb(char *device, int vt_num, struct picture *pict){
-
int fd, vt_old, i,j;
-
struct fb_fix_screeninfo fb_fixinfo;
-
struct fb_var_screeninfo fb_varinfo;
-
struct vt_stat vt_info;
-
-
if (vt_num!=-1){
-
if ((fd = open("/dev/console", O_RDONLY)) == -1)
-
FatalError("could not open /dev/console");
-
if (ioctl(fd, VT_GETSTATE, &vt_info))
-
FatalError("ioctl VT_GETSTATE");
-
close (fd);
-
vt_old=vt_info.v_active;
-
}
-
-
if(!(fd=open(device, O_RDONLY)))
-
FatalError("Couldn't open framebuffer device");
-
-
if (ioctl(fd, FBIOGET_FSCREENINFO, &fb_fixinfo))
-
FatalError("ioctl FBIOGET_FSCREENINFO");
-
-
if (ioctl(fd, FBIOGET_VSCREENINFO, &fb_varinfo))
-
FatalError("ioctl FBIOGET_VSCREENINFO");
-
-
pict->xres=fb_varinfo.xres;
-
pict->yres=fb_varinfo.yres;
-
pict->bps=fb_varinfo.bits_per_pixel;
-
pict->gray=fb_varinfo.grayscale;
-
-
if(fb_fixinfo.visual==FB_VISUAL_PSEUDOCOLOR){
-
pict->colormap=(struct fb_cmap*)malloc(sizeof(struct fb_cmap));
-
pict->colormap->red=(__u16*)malloc(sizeof(__u16)*(1<<pict->bps));
-
pict->colormap->green=(__u16*)malloc(sizeof(__u16)*(1<<pict->bps));
-
pict->colormap->blue=(__u16*)malloc(sizeof(__u16)*(1<<pict->bps));
-
pict->colormap->transp=(__u16*)malloc(sizeof(__u16)*(1<<pict->bps));
-
pict->colormap->start=0;
-
pict->colormap->len=1<<pict->bps;
-
if (ioctl(fd, FBIOGETCMAP, pict->colormap))
-
FatalError("ioctl FBIOGETCMAP");
-
}
-
if (vt_num!=-1)
-
chvt(vt_old);
-
-
switch(pict->bps){
-
case 15:
-
i=2;
-
break;
-
default:
-
i=pict->bps>>3;
-
}
-
-
if(!(pict->buffer=malloc(pict->xres*pict->yres*i)))
-
FatalError("couldnt malloc");
-
-
// fprintf(stdout, "Framebuffer %s is %i bytes.\n", device,
-
// (fb_varinfo.xres * fb_varinfo.yres * i));
-
// fprintf(stdout, "Grabbing %ix%i ... \n", fb_varinfo.xres, fb_varinfo.yres);
-
//
-
//#ifdef DEBUG
-
///* Output some more information bout actual graphics mode
-
// */
-
// fprintf(stdout, "%ix%i [%i,%i] %ibps %igr\n",
-
// fb_varinfo.xres_virtual, fb_varinfo.yres_virtual,
-
// fb_varinfo.xoffset, fb_varinfo.yoffset,
-
// fb_varinfo.bits_per_pixel, fb_varinfo.grayscale);
-
// fprintf(stdout, "FIX: card:%s mem:0x%.8X mem_len:%d visual:%i type:%i type_aux:%i line_len:%i accel:%i\n",
-
// fb_fixinfo.id,fb_fixinfo.smem_start,fb_fixinfo.smem_len,fb_fixinfo.visual,
-
// fb_fixinfo.type,fb_fixinfo.type_aux,fb_fixinfo.line_length,fb_fixinfo.accel);
-
//#endif
-
-
fflush(stdout);
-
if (vt_num!=-1)
-
chvt(vt_num);
-
-
j= (read(fd, pict->buffer, ((pict->xres * pict->yres) * i) )!=
-
(pict->xres * pict->yres *i ));
-
//#ifdef DEBUG
-
// printf("to read:%i read:%i\n",(pict->xres* pict->yres * i), j);
-
//#endif
-
if (vt_num!=-1)
-
chvt(vt_old);
-
-
// if(j)
-
// FatalError("couldn't read the framebuffer");
-
// else
-
// fprintf(stdout,"done.\n");
-
close (fd);
-
-
unify(pict, &fb_varinfo);
-
return 0;
-
}
-
-
-
void convert8to32(struct picture *pict){
-
int i;
-
int j=0;
-
__u8 c;
-
char *out=(char*)malloc(pict->xres*pict->yres*4);
-
for (i=0; i<pict->xres*pict->yres; i++)
-
{
-
c = ((__u8*)(pict->buffer))[i];
-
out[j++]=(char)(pict->colormap->red[c]);
-
out[j++]=(char)(pict->colormap->green[c]);
-
out[j++]=(char)(pict->colormap->blue[c]);
-
out[j++]=(char)(pict->colormap->transp[c]);
-
}
-
free(pict->buffer);
-
pict->buffer=out;
-
}
-
-
void convert1555to32(struct picture *pict){
-
int i;
-
int j=0;
-
__u16 t,c;
-
char *out=(char*)malloc(pict->xres*pict->yres*4);
-
for (i=0; i<pict->xres*pict->yres; i++)
-
{
-
c = ( (__u16*)(pict->buffer))[i];
-
out[j++]=(char)RED1555(c);
-
out[j++]=(char)GREEN1555(c);
-
out[j++]=(char)BLUE1555(c);
-
out[j++]=(char)ALPHA1555(c);
-
}
-
free(pict->buffer);
-
pict->buffer=out;
-
}
-
-
void convert565to32(struct picture *pict){ // ARGB_8888
-
int i;
-
int j=0;
-
__u16 t,c;
-
char *out=(char*)malloc(pict->xres*pict->yres*4);
-
for (i=0; i<pict->xres*pict->yres; i++)
-
{
-
c = ( (__u16*)(pict->buffer))[i];
-
out[j++]=(char)0xff;
-
out[j++]=(char)RED565(c);
-
out[j++]=(char)GREEN565(c);
-
out[j++]=(char)BLUE565(c);
-
-
}
-
free(pict->buffer);
-
pict->buffer=out;
-
}
-
-
-
static int Write(int fd, char* buf, int c)
-
{
-
int i = 0, r;
-
while (i < c)
-
{
-
r = write(fd, (const void*)(buf + i), c - i);
-
i += r;
-
}
-
return i;
-
}
-
-
-
#if 0
-
static int Write_RAW(struct picture* pict, char* filename)
-
{
-
int fd = open(filename, O_CREAT | O_WRONLY | O_SYNC, 0777);
-
if (fd < 0) return -1;
-
-
// convert picture to 32-bit format
-
printf ("BPS: %d\n", pict->bps);
-
switch (pict->bps)
-
{
-
case 8:
-
convert8to32 (pict);
-
break;
-
case 15:
-
convert1555to32 (pict);
-
break;
-
case 16:
-
convert565to32 (pict);
-
break;
-
case 32:
-
break;
-
default:
-
return -1;
-
}
-
-
Write (fd, pict->buffer, pict->xres*pict->yres*4);
-
close (fd);
-
-
return 0;
-
}
-
#endif
-
-
-
static char optstring[] = "hiC:c:d:s:";
-
static struct option long_options[] = {
-
{"slowcon", 1, 0, 'C'},
-
{"console", 1, 0, 'c'},
-
{"device", 1, 0, 'd'},
-
{"help", 0, 0, 'h'},
-
{"noint", 0, 0, 'i'},
-
{"sleep", 1, 0, 's'},
-
{0, 0, 0, 0}
-
};
-
-
-
int TakeScreenshot (char* device, struct picture* pict)
-
{
-
int vt_num = -1;
-
return read_fb(device, vt_num, pict);
-
}
common.h
- #ifndef COMMON_H
-
#define COMMON_H
-
-
struct picture{
-
int xres,yres;
-
char *buffer;
-
struct fb_cmap *colormap;
-
char bps,gray;
-
};
-
-
int TakeScreenshot (char* device, struct picture* pict);
-
-
#endif
阅读(3419) | 评论(0) | 转发(0) |