diff options
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/allformats.c | 1 | ||||
-rw-r--r-- | libavformat/avformat.h | 1 | ||||
-rw-r--r-- | libavformat/png.c | 240 |
3 files changed, 242 insertions, 0 deletions
diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 9a5e03a3bc..65819f5c96 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -75,6 +75,7 @@ void av_register_all(void) av_register_image_format(&ppm_image_format); av_register_image_format(&pgmyuv_image_format); av_register_image_format(&yuv_image_format); + av_register_image_format(&png_image_format); /* file protocols */ register_protocol(&file_protocol); diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 504eb2bf60..8aa5330e51 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -235,6 +235,7 @@ extern AVImageFormat pgm_image_format; extern AVImageFormat ppm_image_format; extern AVImageFormat pgmyuv_image_format; extern AVImageFormat yuv_image_format; +extern AVImageFormat png_image_format; /* XXX: use automatic init with either ELF sections or C file parser */ /* modules */ diff --git a/libavformat/png.c b/libavformat/png.c new file mode 100644 index 0000000000..79efdec755 --- /dev/null +++ b/libavformat/png.c @@ -0,0 +1,240 @@ +/* + * PNG image format + * Copyright (c) 2003 Fabrice Bellard. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "avformat.h" + +#include "libpng/png.h" + +extern const uint8_t png_sig[]; + +static int png_probe(AVProbeData *pd) +{ + if (pd->buf_size >= 8 && + memcmp(pd->buf, png_sig, 8) == 0) + return AVPROBE_SCORE_MAX; + else + return 0; +} + +png_voidp PNGAPI +png_memset_check (png_structp png_ptr, png_voidp s1, int value, + png_uint_32 length) +{ + png_size_t size; + + size = (png_size_t)length; + if ((png_uint_32)size != length) + png_error(png_ptr,"Overflow in png_memset_check."); + + return (png_memset (s1, value, size)); + +} + +png_voidp PNGAPI +png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2, + png_uint_32 length) +{ + png_size_t size; + + size = (png_size_t)length; + if ((png_uint_32)size != length) + png_error(png_ptr,"Overflow in png_memcpy_check."); + + return(png_memcpy (s1, s2, size)); +} + +void png_error (png_struct *png_ptr, const char *message) +{ + longjmp(png_ptr->jmpbuf, 0); +} + +void png_warning (png_struct *png_ptr, const char *message) +{ +} + +void PNGAPI +png_chunk_error(png_structp png_ptr, png_const_charp error_message) +{ + char msg[18+64]; + // png_format_buffer(png_ptr, msg, error_message); + png_error(png_ptr, msg); +} + +void PNGAPI +png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) +{ + char msg[18+64]; + // png_format_buffer(png_ptr, msg, warning_message); + png_warning(png_ptr, msg); +} + +void png_read_data (png_struct *png_ptr, png_byte *data, png_uint_32 length) +{ + int ret; + + ret = get_buffer(png_ptr->io_ptr, data, length); + if (ret != length) + png_error (png_ptr, "Read Error"); +} + +void *png_malloc (png_struct *png_ptr, png_uint_32 size) +{ + return av_malloc(size); +} + +void png_free (png_struct *png_ptr, void *ptr) +{ + return av_free(ptr); +} + +static int png_read(ByteIOContext *f, + int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque) +{ + png_struct png_struct1, *png_ptr; + png_info png_info1, png_info2, *info_ptr, *end_info; + AVImageInfo info1, *info = &info1; + int y, height, ret, row_size; + uint8_t *ptr; + + png_ptr = &png_struct1; + png_read_init(png_ptr); + + info_ptr = &png_info1; + end_info = &png_info2; + + png_info_init(info_ptr); + png_info_init(end_info); + + png_ptr->io_ptr = f; + + if (setjmp(png_jmpbuf(png_ptr))) { + png_read_destroy (png_ptr, info_ptr, NULL); + return -1; + } + + png_read_info (png_ptr, info_ptr); + + /* init image info */ + info->width = info_ptr->width; + info->height = info_ptr->height; + + if (info_ptr->bit_depth == 8 && + info_ptr->color_type == PNG_COLOR_TYPE_RGB) { + info->pix_fmt = PIX_FMT_RGB24; + row_size = info_ptr->width * 3; + } else if (info_ptr->bit_depth == 8 && + info_ptr->color_type == PNG_COLOR_TYPE_GRAY) { + info->pix_fmt = PIX_FMT_GRAY8; + row_size = info_ptr->width; + } else if (info_ptr->bit_depth == 1 && + info_ptr->color_type == PNG_COLOR_TYPE_GRAY) { + info->pix_fmt = PIX_FMT_MONOBLACK; + row_size = (info_ptr->width + 7) >> 3; + } else { + png_read_destroy (png_ptr, info_ptr, NULL); + return -1; + } + ret = alloc_cb(opaque, info); + if (ret) { + png_read_destroy (png_ptr, info_ptr, NULL); + return ret; + } + + /* now read the whole image */ + png_start_read_image (png_ptr); + + height = info->height; + ptr = info->pict.data[0]; + for (y = 0; y < height; y++) { + png_read_row (png_ptr, NULL, NULL); + memcpy(ptr, png_ptr->row_buf + 1, row_size); + ptr += info->pict.linesize[0]; + } + + png_read_destroy (png_ptr, info_ptr, NULL); + return 0; +} + +void +png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + put_buffer(png_ptr->io_ptr, data, length); +} + +static int png_write(ByteIOContext *pb, AVImageInfo *info) +{ + png_struct png_struct1, *png_ptr; + png_info png_info1, *info_ptr; + int w, h, y; + uint8_t *ptr; + + png_ptr = &png_struct1; + info_ptr = &png_info1; + + png_write_init(png_ptr); + png_info_init(info_ptr); + + png_ptr->io_ptr = pb; + + if (setjmp(png_ptr->jmpbuf)) { + png_write_destroy(png_ptr); + return -1; + } + + w = info->width; + h = info->height; + + info_ptr->width = w; + info_ptr->height = h; + switch(info->pix_fmt) { + case PIX_FMT_RGB24: + info_ptr->bit_depth = 8; + info_ptr->color_type = PNG_COLOR_TYPE_RGB; + break; + case PIX_FMT_GRAY8: + info_ptr->bit_depth = 8; + info_ptr->color_type = PNG_COLOR_TYPE_GRAY; + break; + case PIX_FMT_MONOBLACK: + info_ptr->bit_depth = 1; + info_ptr->color_type = PNG_COLOR_TYPE_GRAY; + break; + default: + return -1; + } + png_write_info(png_ptr, info_ptr); + + ptr = info->pict.data[0]; + for(y=0;y<h;y++) { + png_write_row(png_ptr, ptr); + ptr += info->pict.linesize[0]; + } + png_write_end(png_ptr, info_ptr); + png_write_destroy(png_ptr); + put_flush_packet(pb); + return 0; +} + +AVImageFormat png_image_format = { + "png", + "png", + png_probe, + png_read, + (1 << PIX_FMT_RGB24) | (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_MONOBLACK), + png_write, +}; |