Commit 3019a917 authored by Talustus's avatar Talustus Committed by Dees_Troy

FB2PNG: Add fb2png source to TWRP

  * Add Source of fb2png to TWRP tree
  * Android.mk by PhilZ-cwm6
  * Makefile for CrossCompiling via external toolchan by me (Talustus)

Change-Id: If9680688df6e4c9c567f74f46dfc303566b868ba
parent 74fb2e94
......@@ -333,4 +333,9 @@ ifeq ($(TW_INCLUDE_CRYPTO), true)
include $(commands_recovery_local_path)/crypto/ics/Android.mk
endif
# FB2PNG
ifeq ($(TW_INCLUDE_FB2PNG), true)
include $(commands_recovery_local_path)/fb2png/Android.mk
endif
commands_recovery_local_path :=
*.o
fb2png
adb_screenshoot
libs
obj
# Makefile for Android to build fb2png
#
# Copyright (C) 2012 Kyan <kyan.ql.he@gmail.com>
#
# This program 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.
#
# This program 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 along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#Ported to CWM source for PhilZ Touch recovery
#Special thanks to talustus for his help in cross compiling and the Makefile
#Thanks to McKael @xda for his help in fixing for Nexus 4
LOCAL_PATH:= $(call my-dir)
# We need to build this for both the device (as a shared library)
# and the host (as a static library for tools to use).
# <-- Build libpng
include $(CLEAR_VARS)
LOCAL_MODULE := libpng
LOCAL_SRC_FILES := libpng/lib/libpng.a
include $(PREBUILT_STATIC_LIBRARY)
# -->
# <-- Build libfb2png
include $(CLEAR_VARS)
LOCAL_MODULE := libfb2png
LOCAL_SRC_FILES := \
fb2png.c \
img_process.c \
fb.c
LOCAL_C_INCLUDES +=\
external/libpng\
external/zlib
LOCAL_CFLAGS += -DANDROID
LOCAL_STATIC_LIBRARIES := libpng libz
include $(BUILD_STATIC_LIBRARY)
# -->
# <-- Build fb2png bin
include $(CLEAR_VARS)
LOCAL_SRC_FILES := main.c
LOCAL_MODULE := fb2png
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_TAGS := eng
LOCAL_CFLAGS += -DANDROID
LOCAL_STATIC_LIBRARIES := libfb2png libpng libz libc
LOCAL_C_INCLUDES +=\
external/libpng\
external/zlib
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
include $(BUILD_EXECUTABLE)
# -->
/*
* Author: Kyan He <kyan.ql.he@gmail.com>
*
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
# NDK
CC := arm-linux-androideabi-gcc
CFLAGS += -g -static -DANDROID
LDFLAGS += -lpng -lz -lm
ALL: fb2png adb_screenshoot
fb2png: main.o fb.o img_process.o fb2png.o
$(CC) $(CFLAGS) main.o fb.o img_process.o fb2png.o -o fb2png $(LDFLAGS)
# $(CC) $(CFLAGS) main.o fb.o img_process.o fb2png.o -o fb2png
adb_screenshoot: adb_screenshoot.o fb.o img_process.o
$(CC) $(CFLAGS) adb_screenshoot.o fb.o img_process.o -o adb_screenshoot $(LDFLAGS)
clean:
rm -f *.o
rm -f fb2png adb_screenshoot
/*
* -- http://android-fb2png.googlecode.com/svn/trunk/adb_screenshoot.c --
*
* Copyright 2011, Kyan He <kyan.ql.he@gmail.com>
*
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include "fb.h"
#include "log.h"
#define DEFAULT_SAVE_PATH "fbdump.png"
/* defined in $T/system/core/adb/framebuffer_service.c */
#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));
static int remote_socket(const char *host, int port)
{
struct sockaddr_in sa;
struct hostent *hp;
int s;
if(!(hp = gethostbyname(host))){ return -1; }
memset(&sa, 0, sizeof(sa));
sa.sin_port = htons(port);
sa.sin_family = hp->h_addrtype;
memcpy((void*) &sa.sin_addr, (void*) hp->h_addr, hp->h_length);
if((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
return -1;
}
if(connect(s, (struct sockaddr*) &sa, sizeof(sa)) != 0){
close(s);
return -1;
}
return s;
}
char *target = "usb";
static int adb_fd;
/**
* Write command through adb protocol.
* Return
* Bytes have been wrote.
*/
static int adb_write(const char *cmd)
{
char buf[1024];
int sz;
/* Construct command. */
sz = sprintf(buf, "%04x%s", strlen(cmd), cmd);
write(adb_fd, buf, sz);
#if 0
D("<< %s", buf);
#endif
return sz;
}
/**
* Read data through adb protocol.
* Return
* Bytes have been read.
*/
static int adb_read(char *buf, int sz)
{
sz = read(adb_fd, buf, sz);
if (sz < 0) {
E("Fail to read from adb socket, %s", strerror(errno));
}
buf[sz] = '\0';
#if 0
D(">> %d", sz);
#endif
return sz;
}
static int get_fb_from_adb(struct fb *fb)
{
char buf[1024];
const struct fbinfo* fbinfo;
/* Init socket */
adb_fd = remote_socket("localhost", 5037);
if (adb_fd < 0) {
E("Fail to create socket, %s", strerror(errno));
}
adb_write("host:transport-");
adb_read(buf, 1024);
adb_write("framebuffer:");
adb_read(buf, 1024);
/* Parse FB header. */
adb_read(buf, sizeof(struct fbinfo));
fbinfo = (struct fbinfo*) buf;
if (fbinfo->version != DDMS_RAWIMAGE_VERSION) {
E("unspport adb version");
}
/* Assemble struct fb */
memcpy(fb, &fbinfo->bpp, sizeof(struct fbinfo) - 4);
fb_dump(fb);
fb->data = malloc(fb->size);
if (!fb->data) return -1;
/* Read out the whole framebuffer */
int bytes_read = 0;
while (bytes_read < fb->size) {
bytes_read += adb_read(fb->data + bytes_read, fb->size - bytes_read);
}
return 0;
}
int fb2png(const char* path)
{
struct fb fb;
if (get_fb_from_adb(&fb)) {
D("cannot get framebuffer.");
return -1;
}
return fb_save_png(&fb, path);
}
int main(int argc, char *argv[])
{
char fn[128];
if (argc == 2) {
//if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
if (argv[1][0] == '-') {
printf(
"Usage: fb2png [path/to/output.png]\n"
" The default output path is ./fbdump.png\n"
);
exit(0);
} else {
sprintf(fn, "%s", argv[1]);
}
} else {
sprintf(fn, "%s", DEFAULT_SAVE_PATH);
}
return fb2png(fn);
}
#!/usr/bin/python
import socket
import sys
import struct
import time
# debug
VERBOSE = True
def D(msg):
if VERBOSE: print(msg)
# "struct fbinfo" is defined in $T/system/core/adb/framebuffer_service.c
def fbinfo_unpack(data):
keys = ("version",
"bpp",
"size",
"width",
"height",
"red_offset",
"red_length",
"blue_offset",
"blue_length",
"green_offset",
"green_length",
"alpha_offset",
"alpha_length"
)
# the data is little-endian
values = struct.unpack("<IIIIIIIIIIIII",data)
D("dump struct fbinfo")
i = 0
for key in keys:
D("%14s: %-12d" % (key, values[i]))
i = i + 1
def save():
f = open('dump', 'w')
while True:
data = s.recv(4096 * 16)
if data == "":
break
f.write(data)
f.close()
def communicate(cmd=None):
if cmd != None:
buf = "%04x%s" % (len(cmd), cmd)
D("<< " + buf)
s.send(buf)
data = s.recv(4096)
D(">> [%s]" % len(data))
D(data)
if data[0:4] == 'FAIL':
return False
else:
return True
target = ''
# use getopt module in future
for arg in sys.argv:
if arg == '-q':
VERBOSE = False
if target != 'any':
# compatiable with "adb -d", redirect commands to usb
if arg == '-d':
target = 'usb'
# compatiable with "adb -e", redirect commands to emulator
elif arg == '-e':
target = 'local'
if target == '': target ='any'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
D("connecting")
try:
s.connect(("localhost", 5037))
except socket.error:
print 'Cannot connect to localhost:5037'
print socket.error
sys.exit(0)
D("connected")
if not communicate("host:transport-%s" % target):
sys.exit(1)
#communicate("host:transport-usb:shell:ls /data")
communicate("framebuffer:")
data = s.recv(52)
fbinfo_unpack(data)
t0 = float(time.time())
save()
t1 = float(time.time())
print t1 - t0
/*
* -- http://android-fb2png.googlecode.com/svn/trunk/fb.c --
*
* Copyright 2011, Kyan He <kyan.ql.he@gmail.com>
*
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "log.h"
#include "fb.h"
#include "img_process.h"
void fb_dump(const struct fb* fb)
{
D("%12s : %d", "bpp", fb->bpp);
D("%12s : %d", "size", fb->size);
D("%12s : %d", "width", fb->width);
D("%12s : %d", "height", fb->height);
D("%12s : %d %d %d %d", "ARGB offset",
fb->alpha_offset, fb->red_offset,
fb->green_offset, fb->blue_offset);
D("%12s : %d %d %d %d", "ARGB length",
fb->alpha_length, fb->red_length,
fb->green_length, fb->blue_length);
}
/**
* Returns the format of fb.
*/
static int fb_get_format(const struct fb *fb)
{
int ao = fb->alpha_offset;
int ro = fb->red_offset;
int go = fb->green_offset;
int bo = fb->blue_offset;
#define FB_FORMAT_UNKNOWN 0
#define FB_FORMAT_RGB565 1
#define FB_FORMAT_ARGB8888 2
#define FB_FORMAT_RGBA8888 3
#define FB_FORMAT_ABGR8888 4
#define FB_FORMAT_BGRA8888 5
/* TODO: use offset */
if (fb->bpp == 16)
return FB_FORMAT_RGB565;
/* TODO: validate */
if (ao == 0 && ro == 8)
return FB_FORMAT_ARGB8888;
if (ao == 0 && bo == 8)
return FB_FORMAT_ABGR8888;
if (ro == 0)
return FB_FORMAT_RGBA8888;
if (bo == 0)
return FB_FORMAT_BGRA8888;
/* fallback */
return FB_FORMAT_UNKNOWN;
}
int fb_save_png(const struct fb *fb, const char *path)
{
char *rgb_matrix;
int ret = -1;
/* Allocate RGB Matrix. */
rgb_matrix = malloc(fb->width * fb->height * 3);
if(!rgb_matrix) {
free(rgb_matrix);
return -1;
}
int fmt = fb_get_format(fb);
D("Framebuffer Pixel Format: %d", fmt);
switch(fmt) {
case FB_FORMAT_RGB565:
/* emulator use rgb565 */
ret = rgb565_to_rgb888(fb->data,
rgb_matrix, fb->width * fb->height);
break;
case FB_FORMAT_ARGB8888:
/* most devices use argb8888 */
ret = argb8888_to_rgb888(fb->data,
rgb_matrix, fb->width * fb->height);
break;
case FB_FORMAT_ABGR8888:
ret = abgr8888_to_rgb888(fb->data,
rgb_matrix, fb->width * fb->height);
break;
case FB_FORMAT_BGRA8888:
ret = bgra8888_to_rgb888(fb->data,
rgb_matrix, fb->width * fb->height);
break;
case FB_FORMAT_RGBA8888:
ret = rgba8888_to_rgb888(fb->data,
rgb_matrix, fb->width * fb->height);
break;
default:
D("Unsupported framebuffer type.");
break;
}
if (ret != 0)
D("Error while processing input image.");
else if (0 != (ret = save_png(path, rgb_matrix, fb->width, fb->height)))
D("Failed to save in PNG format.");
free(rgb_matrix);
return ret;
}
/*
* -- http://android-fb2png.googlecode.com/svn/trunk/fb.h --
*
* Copyright 2011, Kyan He <kyan.ql.he@gmail.com>
*
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FB_H__
#define __FB_H__
struct fb {
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;
void* data;
};
int fb_save_png(const struct fb *fb, const char *path);
#endif
/*
* -- http://android-fb2png.googlecode.com/svn/trunk/fb2png-jni.c --
*
* Copyright 2011, Kyan He <kyan.ql.he@gmail.com>
*
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <jni.h>
#include "fb2png.h"
jint Java_im_kyan_android_graphics_FrameBuffer_captureScreen( JNIEnv *env,
jobject this,
jstring path )
{
return fb2png("/data/local/fbdump.png");
}
/**
* fb2png Save screenshot into .png.
*
* Copyright (C) 2012 Kyan <kyan.ql.he@gmail.com>
*
* This program 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.
*
* This program 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 along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <errno.h>
#include "log.h"
#include "fb2png.h"
#include "fb.h"
/**
* Get the {@code struct fb} from device's framebuffer.
* Return
* 0 for success.
*/
int get_device_fb(const char* path, struct fb *fb)
{
int fd;
int bytespp;
int offset;
char *x;
struct fb_var_screeninfo vinfo;
fd = open(path, O_RDONLY);
if (fd < 0) return -1;
if(ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
D("ioctl failed, %s\n", strerror(errno));
return -1;
}
bytespp = vinfo.bits_per_pixel / 8;
fb->bpp = vinfo.bits_per_pixel;
fb->size = vinfo.xres * vinfo.yres * bytespp;
fb->width = vinfo.xres;
fb->height = vinfo.yres;
fb->red_offset = vinfo.red.offset;
fb->red_length = vinfo.red.length;
fb->green_offset = vinfo.green.offset;
fb->green_length = vinfo.green.length;
fb->blue_offset = vinfo.blue.offset;
fb->blue_length = vinfo.blue.length;
fb->alpha_offset = vinfo.transp.offset;
fb->alpha_length = vinfo.transp.length;
#ifdef ANDROID
/* HACK: for several of 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;
/* Android use double-buffer, capture 2nd */
offset += vinfo.xres * vinfo.yoffset * bytespp;
#else
offset = 0;
#endif
x = malloc(fb->size);
if (!x) return -1;
lseek(fd, offset, SEEK_SET);
if (read(fd, x ,fb->size) != fb->size) goto oops;
fb->data = x;
close(fd);
return 0;
oops:
close(fd);
free(x);
return -1;
}
int fb2png(const char *path)
{
struct fb fb;
int ret;
#ifdef ANDROID
ret = get_device_fb("/dev/graphics/fb0", &fb);
#else
ret = get_device_fb("/dev/fb0", &fb);
#endif
if (ret) {
D("Failed to read framebuffer.");
return -1;