diff options
author | Kent Mein <mein@cs.umn.edu> | 2003-12-04 21:18:05 +0300 |
---|---|---|
committer | Kent Mein <mein@cs.umn.edu> | 2003-12-04 21:18:05 +0300 |
commit | 24624501a473c13f6a6d9c4676cbdd33b4a88e73 (patch) | |
tree | 6b0c79b38b21da22fac3e0a6f141b970e610b473 /source/blender/imbuf/intern/png.c | |
parent | 43369f076f3be5000f56079f31767ffc3e730d2b (diff) |
This looks like a lot but its a few small changes.
Summary: standardized imageformat functions(make function names similar, and
parameters in same order where relavant), small code cleanups, and
added a description of how to add an image format to blender.
Kent
Specifics:
merged png_decode.c and png_encode.c to png.c and cleaned function calls.
fixed some spacing in IMB_imbuf_types.h
casting cleanups:
intern/amiga.c
intern/ham.c
intern/iris.c
Modified switch statements to have a default type to insure values are set:
intern/antialias.c
Initalization of some vars and make types similar.
intern/bitplanes.c
cleaned function calls, and changed if else to if's with return:
intern/jpeg.c
added {}'s in multidemensional arrays.
intern/matrix.h
Made a little cleaner to read, and matched above changes.
intern/readimage.c
intern/writeimage.c
Diffstat (limited to 'source/blender/imbuf/intern/png.c')
-rw-r--r-- | source/blender/imbuf/intern/png.c | 427 |
1 files changed, 427 insertions, 0 deletions
diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c new file mode 100644 index 00000000000..d8ec1a293dc --- /dev/null +++ b/source/blender/imbuf/intern/png.c @@ -0,0 +1,427 @@ +/** + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * $Id$ + */ + + +#include "png.h" + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif +#include "BLI_blenlib.h" + +#include "imbuf.h" +#include "imbuf_patch.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#include "IMB_allocimbuf.h" +#include "IMB_cmap.h" +#include "IMB_png.h" + +typedef struct PNGReadStruct { + unsigned char *data; + unsigned int size; + unsigned int seek; +}PNGReadStruct; + +static void ReadData( png_structp png_ptr, png_bytep data, png_size_t length); +static void WriteData( png_structp png_ptr, png_bytep data, png_size_t length); +static void Flush( png_structp png_ptr); + +int imb_is_a_png(void *mem) +{ + int ret_val = 0; + + if (mem) { + ret_val = !png_sig_cmp(mem, 0, 8); + } + + return(ret_val); +} + +static void Flush(png_structp png_ptr) +{ +} + +static void WriteData( png_structp png_ptr, png_bytep data, png_size_t length) +{ + ImBuf *ibuf = (ImBuf *) png_get_io_ptr(png_ptr); + + // if buffer is to small increase it. + while (ibuf->encodedsize + length > ibuf->encodedbuffersize) { + imb_enlargeencodedbufferImBuf(ibuf); + } + + memcpy(ibuf->encodedbuffer + ibuf->encodedsize, data, length); + ibuf->encodedsize += length; +} + +static void ReadData( png_structp png_ptr, png_bytep data, png_size_t length) +{ + PNGReadStruct *rs= (PNGReadStruct *) png_get_io_ptr(png_ptr); + + if (rs) { + if (length <= rs->size - rs->seek) { + memcpy(data, rs->data + rs->seek, length); + rs->seek += length; + return; + } + } + + printf("Reached EOF while decoding PNG\n"); + longjmp(png_jmpbuf(png_ptr), 1); +} + +short imb_savepng(struct ImBuf *ibuf, int file, int flags) +{ + png_structp png_ptr; + png_infop info_ptr; + unsigned char *pixels = 0; + unsigned char *from, *to; + png_bytepp row_pointers = 0; + int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY; + FILE *fp = 0; + + bytesperpixel = (ibuf->depth + 7) >> 3; + if ((bytesperpixel > 4) || (bytesperpixel == 2)) { + printf("imb_savepng: unsupported bytes per pixel: %d\n", bytesperpixel); + return (0); + } + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL); + if (png_ptr == NULL) { + printf("Cannot png_create_write_struct\n"); + return 0; + } + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + printf("Cannot png_create_info_struct\n"); + return 0; + } + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + if (pixels) MEM_freeN(pixels); + if (row_pointers) MEM_freeN(row_pointers); + // printf("Aborting\n"); + if (fp) { + fflush(fp); + fclose(fp); + } + return 0; + } + + // copy image data + + pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels"); + if (pixels == NULL) { + printf("Cannot allocate pixels array\n"); + return 0; + } + + from = (unsigned char *) ibuf->rect; + to = pixels; + + switch (bytesperpixel) { + case 4: + color_type = PNG_COLOR_TYPE_RGBA; + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = from[3]; + to += 4; from += 4; + } + break; + case 3: + color_type = PNG_COLOR_TYPE_RGB; + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to += 3; from += 4; + } + break; + case 1: + color_type = PNG_COLOR_TYPE_GRAY; + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to[0] = from[0]; + to++; from += 4; + } + break; + } + + if (flags & IB_mem) { + // create image in memory + imb_addencodedbufferImBuf(ibuf); + ibuf->encodedsize = 0; + + png_set_write_fn(png_ptr, + (png_voidp) ibuf, + WriteData, + Flush); + } else { + fp = fdopen(file, "wb"); + png_init_io(png_ptr, fp); + } + + /* + png_set_filter(png_ptr, 0, + PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | + PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | + PNG_FILTER_UP | PNG_FILTER_VALUE_UP | + PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG | + PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH| + PNG_ALL_FILTERS); + + png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); + */ + + // png image settings + png_set_IHDR(png_ptr, + info_ptr, + ibuf->x, + ibuf->y, + 8, + color_type, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + // write the file header information + png_write_info(png_ptr, info_ptr); + + // allocate memory for an array of row-pointers + row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers"); + if (row_pointers == NULL) { + printf("Cannot allocate row-pointers array\n"); + return 0; + } + + // set the individual row-pointers to point at the correct offsets + for (i = 0; i < ibuf->y; i++) { + row_pointers[ibuf->y-1-i] = (png_bytep) + ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char)); + } + + // write out the entire image data in one call + png_write_image(png_ptr, row_pointers); + + // write the additional chunks to the PNG file (not really needed) + png_write_end(png_ptr, info_ptr); + + // clean up + MEM_freeN(pixels); + MEM_freeN(row_pointers); + png_destroy_write_struct(&png_ptr, &info_ptr); + + if (fp) { + fflush(fp); + fclose(fp); + } + + return(1); +} + +struct ImBuf *imb_loadpng(unsigned char *mem, int size, int flags) +{ + struct ImBuf *ibuf = 0; + png_structp png_ptr; + png_infop info_ptr; + unsigned char *pixels = 0; + png_bytepp row_pointers = 0; + png_uint_32 width, height; + int bit_depth, color_type; + PNGReadStruct ps; + + unsigned char *from, *to; + int i, bytesperpixel; + + if (imb_is_a_png(mem) == 0) return(0); + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL); + if (png_ptr == NULL) { + printf("Cannot png_create_read_struct\n"); + return 0; + } + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, + (png_infopp)NULL); + printf("Cannot png_create_info_struct\n"); + return 0; + } + + ps.size = size; + ps.data = mem; + ps.seek = 0; + + png_set_read_fn(png_ptr, (void *) &ps, ReadData); + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + if (pixels) MEM_freeN(pixels); + if (row_pointers) MEM_freeN(row_pointers); + if (ibuf) IMB_freeImBuf(ibuf); + return 0; + } + + // png_set_sig_bytes(png_ptr, 8); + + png_read_info(png_ptr, info_ptr); + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, + &color_type, NULL, NULL, NULL); + + if (bit_depth == 16) { + png_set_strip_16(png_ptr); + bit_depth = 8; + } + + bytesperpixel = png_get_channels(png_ptr, info_ptr); + + switch(color_type) { + case PNG_COLOR_TYPE_RGB: + case PNG_COLOR_TYPE_RGB_ALPHA: + break; + case PNG_COLOR_TYPE_PALETTE: + png_set_palette_to_rgb(png_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + bytesperpixel = 4; + } else { + bytesperpixel = 3; + } + break; + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (bit_depth < 8) { + png_set_expand(png_ptr); + bit_depth = 8; + } + break; + default: + printf("PNG format not supported\n"); + longjmp(png_jmpbuf(png_ptr), 1); + } + + ibuf = IMB_allocImBuf(width, height, 8 * bytesperpixel, 0, 0); + + if (ibuf) { + ibuf->ftype = PNG; + } else { + printf("Couldn't allocate memory for PNG image\n"); + } + + if (ibuf && ((flags & IB_test) == 0)) { + imb_addrectImBuf(ibuf); + + pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels"); + if (pixels == NULL) { + printf("Cannot allocate pixels array\n"); + longjmp(png_jmpbuf(png_ptr), 1); + } + + // allocate memory for an array of row-pointers + row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers"); + if (row_pointers == NULL) { + printf("Cannot allocate row-pointers array\n"); + longjmp(png_jmpbuf(png_ptr), 1); + } + + // set the individual row-pointers to point at the correct offsets + for (i = 0; i < ibuf->y; i++) { + row_pointers[ibuf->y-1-i] = (png_bytep) + ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char)); + } + + png_read_image(png_ptr, row_pointers); + + // copy image data + + to = (unsigned char *) ibuf->rect; + from = pixels; + + switch (bytesperpixel) { + case 4: + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = from[3]; + to += 4; from += 4; + } + break; + case 3: + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = 0xff; + to += 4; from += 3; + } + break; + case 2: + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to[0] = to[1] = to[2] = from[0]; + to[3] = from[1]; + to += 4; from += 2; + } + break; + case 1: + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to[0] = to[1] = to[2] = from[0]; + to[3] = 0xff; + to += 4; from++; + } + break; + } + + png_read_end(png_ptr, info_ptr); + } + + // clean up + MEM_freeN(pixels); + MEM_freeN(row_pointers); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + + return(ibuf); +} + |