/*
* -- http://android-fb2png.googlecode.com/svn/trunk/img_process.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 <errno.h>
#include <png.h>
#include "img_process.h"
#include "log.h"
int rgb565_to_rgb888(const char* src, char* dst, size_t pixel)
{
struct rgb565 *from;
struct rgb888 *to;
from = (struct rgb565 *) src;
to = (struct rgb888 *) dst;
size_t i = 0;
/* traverse pixel of the row */
while(i++ < pixel) {
to->r = from->r;
to->g = from->g;
to->b = from->b;
/* scale */
to->r <<= 3;
to->g <<= 2;
to->b <<= 3;
to++;
from++;
}
return 0;
}
int argb8888_to_rgb888(const char* src, char* dst, size_t pixel)
{
size_t i;
struct argb8888 *from;
struct rgb888 *to;
from = (struct argb8888 *) src;
to = (struct rgb888 *) dst;
i = 0;
/* traverse pixel of the row */
while(i++ < pixel) {
to->r = from->r;
to->g = from->g;
to->b = from->b;
to++;
from++;
}
return 0;
}
int abgr8888_to_rgb888(const char* src, char* dst, size_t pixel)
{
size_t i;
struct abgr8888 *from;
struct rgb888 *to;
from = (struct abgr8888 *) src;
to = (struct rgb888 *) dst;
i = 0;
/* traverse pixel of the row */
while(i++ < pixel) {
to->r = from->r;
to->g = from->g;
to->b = from->b;
to++;
from++;
}
return 0;
}
int bgra8888_to_rgb888(const char* src, char* dst, size_t pixel)
{
size_t i;
struct bgra8888 *from;
struct rgb888 *to;
from = (struct bgra8888 *) src;
to = (struct rgb888 *) dst;
i = 0;
/* traverse pixel of the row */
while(i++ < pixel) {
to->r = from->r;
to->g = from->g;
to->b = from->b;
to++;
from++;
}
return 0;
}
int rgba8888_to_rgb888(const char* src, char* dst, size_t pixel)
{
size_t i;
struct rgba8888 *from;
struct rgb888 *to;
from = (struct rgba8888 *) src;
to = (struct rgb888 *) dst;
i = 0;
/* traverse pixel of the row */
while(i++ < pixel) {
to->r = from->r;
to->g = from->g;
to->b = from->b;
to++;
from++;
}
return 0;
}
static void
stdio_write_func (png_structp png, png_bytep data, png_size_t size)
{
FILE *fp;
size_t ret;
fp = png_get_io_ptr (png);
while (size) {
ret = fwrite (data, 1, size, fp);
size -= ret;
data += ret;
if (size && ferror (fp))
E("write: %m\n");
}
}
static void
png_simple_output_flush_fn (__attribute__((unused)) png_structp png_ptr)
{
}
static void
png_simple_error_callback (__attribute__((unused)) png_structp png,
png_const_charp error_msg)
{
E("png error: %s\n", error_msg);
}
static void
png_simple_warning_callback (__attribute__((unused)) png_structp png,
png_const_charp error_msg)
{
fprintf(stderr, "png warning: %s\n", error_msg);
}
/* save rgb888 to png format in fp */
int save_png(const char* path, const char* data, int width, int height)
{
FILE *fp;
png_byte **volatile rows;
png_struct *png;
png_info *info;
fp = fopen(path, "w");
if (!fp) {
int errsv = errno;
E("Cannot open file %s for writing.\n", path);
return errsv;
}
rows = malloc(height * sizeof rows[0]);
if (!rows) goto oops;
int i;
for (i = 0; i < height; i++)
rows[i] = (png_byte *) data + i * width * 3 /*fb.stride*/;
png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL,
png_simple_error_callback,
png_simple_warning_callback);
if (!png) {
E("png_create_write_struct failed\n");
goto oops;
}
info = png_create_info_struct (png);
if (!info) {
E("png_create_info_struct failed\n");
png_destroy_write_struct (&png, NULL);
goto oops;
}
png_set_write_fn (png, fp, stdio_write_func, png_simple_output_flush_fn);
png_set_IHDR (png, info,
width,
height,
#define DEPTH 8
DEPTH,
PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
png_color_16 white;
white.gray = (1 << DEPTH) - 1;
white.red = white.blue = white.green = white.gray;
png_set_bKGD (png, info, &white);
png_write_info (png, info);
png_write_image (png, rows);
png_write_end (png, info);
png_destroy_write_struct (&png, &info);
fclose(fp);
free (rows);
return 0;
oops:
fclose(fp);
free (rows);
return -1;
}