diff options
Diffstat (limited to 'fb2png/fb.c')
-rw-r--r-- | fb2png/fb.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/fb2png/fb.c b/fb2png/fb.c new file mode 100644 index 000000000..2ed478902 --- /dev/null +++ b/fb2png/fb.c @@ -0,0 +1,132 @@ +/* + * -- 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; +} |