From b694c274836ac8b04d644711ac324eac2e9ab83e Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 16 Dec 2005 01:05:40 +0000 Subject: checking in pdp 0.12.4 from http://zwizwa.fartit.com/pd/pdp/pdp-0.12.4.tar.gz svn path=/trunk/externals/pdp/; revision=4232 --- system/png/pdp_png.c | 409 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 409 insertions(+) create mode 100644 system/png/pdp_png.c (limited to 'system/png/pdp_png.c') diff --git a/system/png/pdp_png.c b/system/png/pdp_png.c new file mode 100644 index 0000000..f751912 --- /dev/null +++ b/system/png/pdp_png.c @@ -0,0 +1,409 @@ + +/* + * Pure Data Packet system module. - png glue code + * Copyright (c) by Tom Schouten + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "pdp_packet.h" +#include "pdp_mem.h" +#include "pdp_post.h" +#include "pdp_debug.h" + +// this is an optional module +#include "pdp_config.h" + + +#ifdef HAVE_PDP_PNG +//if 0 + +#include + +#define READING 1 +#define WRITING 2 +#define SIG_BYTES 8 + +#define D if(0) + +typedef struct +{ + FILE *x_fp; + + int x_kindof; //READING or WRITING + png_structp x_png; + png_infop x_info; + png_infop x_end_info; + + png_uint_32 x_width; + png_uint_32 x_height; + int x_bit_depth; + int x_color_type; + int x_interlace_type; + int x_compression_type; + int x_filter_type; + + int x_pdp_bitmap_type; + int x_packet; + +} t_png_image; + +static t_png_image *_init(t_png_image *x) +{ + x->x_png = 0; + x->x_info = 0; + x->x_end_info = 0; + x->x_fp = 0; + x->x_packet = -1; + return x; +} + +static int _cleanup(t_png_image *x) +{ +#define INTERNAL_ERROR 1 + if (!x) return 1; + pdp_packet_mark_unused(x->x_packet); + if (x->x_png) + switch(x->x_kindof){ + case READING: png_destroy_read_struct(&x->x_png, &x->x_info, &x->x_end_info); break; + case WRITING: png_destroy_write_struct(&x->x_png, &x->x_info); break; + default: PDP_ASSERT(INTERNAL_ERROR); + } + if (x->x_fp) fclose(x->x_fp); + return 1; +} + +static int _open_read(t_png_image* x, char *file) +{ + char header[SIG_BYTES]; + int is_png; + + x->x_fp = fopen(file, "r"); + if (!x->x_fp) { + D pdp_post("can't open %s for reading", file); + return 0; + } + fread(header, 1, SIG_BYTES, x->x_fp); + is_png = !png_sig_cmp(header, 0, SIG_BYTES); + + D pdp_post("%s is %s png file", file, is_png ? "a" : "not a"); + + return is_png; +} + +static int _open_write(t_png_image* x, char *file) +{ + char header[SIG_BYTES]; + int is_png; + + x->x_fp = fopen(file, "w"); + if (!x->x_fp) { + D pdp_post("can't open %s for writing", file); + return 0; + } + + return 1; +} + +/* progress callback */ + +static void _row_callback(png_structp p, png_uint_32 row, int pass) +{ + fprintf(stderr, "."); +} + +static int _initio_read(t_png_image *x) +{ + png_init_io(x->x_png, x->x_fp); + png_set_sig_bytes(x->x_png, SIG_BYTES); + D png_set_read_status_fn(x->x_png, _row_callback); + return 1; + +} + +static int _initio_write(t_png_image *x) +{ + png_init_io(x->x_png, x->x_fp); + D png_set_write_status_fn(x->x_png, _row_callback); + + return 1; + +} + +static int _checkimagetype(t_png_image *x) +{ + png_read_info(x->x_png, x->x_info); + png_get_IHDR(x->x_png, x->x_info, &x->x_width, &x->x_height, + &x->x_bit_depth, &x->x_color_type, &x->x_interlace_type, + &x->x_compression_type, &x->x_filter_type); + + D pdp_post("image info: w=%d, h=%d, depth=%d, type=%d", + (int)x->x_width, (int)x->x_height, (int)x->x_bit_depth, + (int)x->x_color_type); + + + /* handle paletted images: convert to 8 bit RGB(A) */ + if (x->x_color_type == PNG_COLOR_TYPE_PALETTE && + x->x_bit_depth <= 8) { + png_set_expand(x->x_png); + D pdp_post("convert palette"); + + /* check if there's an alpha channel and set PDP_BITMAP type */ + x->x_pdp_bitmap_type = + (png_get_valid(x->x_png, x->x_info, PNG_INFO_tRNS)) ? + PDP_BITMAP_RGBA : PDP_BITMAP_RGB; + + return 1; + } + + /* handle bitdepth */ + if (x->x_bit_depth < 8) { + png_set_expand(x->x_png); + D pdp_post("convert greyscale to 8 bit"); + } + if (x->x_bit_depth == 16){ + D pdp_post("stripping 16 bit to 8 bit"); + png_set_strip_16(x->x_png); + } + + + /* handle greyscale images */ + if (x->x_color_type == PNG_COLOR_TYPE_GRAY){ + x->x_pdp_bitmap_type = PDP_BITMAP_GREY; + if (png_get_valid(x->x_png, x->x_info, PNG_INFO_tRNS)){ + D pdp_post("no support for greyscale images with alpha info"); + return 0; + } + return 1; + } + + /* handle RGB imges */ + if (x->x_color_type = PNG_COLOR_TYPE_RGB){ + x->x_pdp_bitmap_type = PDP_BITMAP_RGB; + return 1; + } + + /* handle RGBA imges */ + if (x->x_color_type = PNG_COLOR_TYPE_RGBA){ + x->x_pdp_bitmap_type = PDP_BITMAP_RGBA; + return 1; + } + + + /* can't handle image type */ + D pdp_post("image type not supported"); + return 0; + +} + +#define user_error_ptr NULL +#define user_error_fn NULL +#define user_warning_fn NULL + +static int _buildstruct_read(t_png_image *x) +{ + x->x_kindof = READING; + + if (!(x->x_png = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn))) return 0; + + if (!(x->x_info = png_create_info_struct(x->x_png))) return 0; + if (!(x->x_end_info = png_create_info_struct(x->x_png))) return 0; + + return 1; +} + +static int _buildstruct_write(t_png_image *x) +{ + x->x_kindof = WRITING; + + if (!(x->x_png = png_create_write_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn))) return 0; + + if (!(x->x_info = png_create_info_struct(x->x_png))) return 0; + + return 1; +} + +static int _getimagedata(t_png_image *x) +{ + int nbchans = 0; + char *image_data; + png_bytep row_pointers[x->x_height]; + png_uint_32 i; + + D pdp_post("reading %d rows ", (int)x->x_height); + + switch (x->x_pdp_bitmap_type){ + case PDP_BITMAP_GREY: nbchans = 1; break; + case PDP_BITMAP_RGB: nbchans = 3; break; + case PDP_BITMAP_RGBA: nbchans = 4; break; + default: + return 0; + } + + x->x_packet = + pdp_packet_new_bitmap(x->x_pdp_bitmap_type, x->x_width, x->x_height); + if (!(image_data = pdp_packet_data(x->x_packet))) return 0; + + for(i=0; ix_height; i++) + row_pointers[i] = image_data + nbchans * i * x->x_width; + + png_read_image(x->x_png, row_pointers); + + D pdp_post("DONE"); + + return 1; +} + +static int _saveimagedata(t_png_image *x, int packet) +{ + png_bytep *row_pointers; + png_uint_32 i; + int nbchans; + t_pdp *h = pdp_packet_header(packet); + char *image_data = (char *)pdp_packet_data(packet); + + if (!h) return 0; + if (PDP_BITMAP != h->type) return 0; + if (!image_data) return 0; + + x->x_width = h->info.bitmap.width; + x->x_height = h->info.bitmap.height; + + switch(h->info.image.encoding){ + case PDP_BITMAP_GREY: x->x_color_type = PNG_COLOR_TYPE_GRAY; nbchans = 1; break; + case PDP_BITMAP_RGB: x->x_color_type = PNG_COLOR_TYPE_RGB; nbchans = 3; break; + case PDP_BITMAP_RGBA: x->x_color_type = PNG_COLOR_TYPE_RGBA; nbchans = 4; break; + default: return 0; + } + + png_set_IHDR(x->x_png, x->x_info, x->x_width, x->x_height, 8, + x->x_color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + png_write_info(x->x_png, x->x_info); + + D pdp_post("writing %d rows ", (int)x->x_height); + + row_pointers = (png_bytep *)pdp_alloc(sizeof(png_bytep) * x->x_height); + for(i=0; ix_height; i++) + row_pointers[i] = image_data + nbchans * i * x->x_width; + + png_write_image(x->x_png, row_pointers); + png_write_end(x->x_png, x->x_info); + pdp_dealloc(row_pointers); + + D pdp_post("DONE"); + + return 1; +} + + + +/* simple functions to load and save png images */ + +int pdp_packet_bitmap_from_png_file(char *filename) +{ + int packet = -1; + t_png_image _x; + t_png_image *x = &_x; + + if (!_init(x)) goto exit; + if (!_open_read(x, filename)) goto exit; + if (!_buildstruct_read(x)) goto exit; + if (!_initio_read(x)) goto exit; + if (!_checkimagetype(x)) goto exit; + if (!_getimagedata(x)) goto exit; + + packet = x->x_packet; + x->x_packet = -1; + _cleanup(x); + return packet; + exit: + _cleanup(x); + return -1; + +} + + + +int pdp_packet_bitmap_save_png_file(int packet, char *filename) +{ + + t_png_image _x; + t_png_image *x = &_x; + + if (!_init(x)) goto exit; + if (!_open_write(x, filename)) goto exit; + if (!_buildstruct_write(x)) goto exit; + if (!_initio_write(x)) goto exit; + if (!_saveimagedata(x, packet)) goto exit; + + _cleanup(x); + return 1; + exit: + _cleanup(x); + return 0; + +} + + + +#else //PDP_HAVE_PNG +int pdp_packet_bitmap_save_png_file(int packet, char *filename) +{ + pdp_post("WARNING: no png support, can't save png file %s", filename); + return 0; +} + +int pdp_packet_bitmap_from_png_file(char *filename) +{ + pdp_post("WARNING: no png support, can't load png file %s", filename); + return -1; +} + + +#endif //PDP_HAVE_PNG + + + + + + + + + + + + + +#if 0 +int main(int argc, char **argv) +{ + char *image = 0; + + if (argc != 2) + pdp_post("usage: %s ", argv[0]); + else + image = load_png(argv[1]); + + pdp_post ("%s", image ? "OK" : "ERROR"); + +} +#endif -- cgit v1.2.1