Mercurial > hg > octave-image
view src/pngread.cc @ 249:4023b90892ff
FSF address update
author | adb014 |
---|---|
date | Fri, 23 Mar 2007 20:59:58 +0000 |
parents | 8fe38c1c25c5 |
children | 3da7ef6dd4ee |
line wrap: on
line source
/* * pngread.cc * * Copyright (C) 2003 Nadav Rotem <nadav256@hotmail.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 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Load PNG files to octave using libpng; PNG (Portable Network Graphics) is an extensible file format for the lossless, portable, well-compressed storage of raster images. PNG pro- vides a patent-free replacement for GIF and can also replace many com- mon uses of TIFF. Indexed-color, grayscale, and truecolor images are supported, plus an optional alpha channel. Sample depths range from 1 to 16 bits. */ /* * Modified: Stefan van der Walt <stefan@sun.ac.za> * Date: 28 January 2005 * - Fix bugs, restructure */ #include "png.h" #include "pngcanvas.h" #include <octave/oct.h> canvas *load_canvas(char *filename); DEFUN_DLD (pngread, args, nargout , "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {[@var{I}, @var{alpha}] =} pngread(@var{filename})\n\ \n\ Read a PNG file from disk.\n\ \n\ The image is returned as a matrix of dimension MxN (for grey-level images)\n\ or MxNx3 (for colour images). The numeric type of @var{I} and @var{alpha}\n\ is @code{uint8} for grey-level and RGB images, or @code{logical} for\n\ black-and-white images.\n\ \n\ @end deftypefn\n\ @seealso{imread}") { octave_value_list retval; int nargin = args.length(); // // We bail out if the input parameters are bad // if (nargin != 1 || !args(0).is_string()) { print_usage (); return retval; } // // Load png file // canvas *pic=load_canvas((char *)args(0).string_value().c_str()); if (!pic) return retval; dim_vector dim = dim_vector(); dim.resize(3); dim(0) = pic->height; dim(1) = pic->width; dim(2) = 3; if ( (pic->color_type == PNG_COLOR_TYPE_GRAY) || (pic->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) || ((pic->color_type == PNG_COLOR_TYPE_PALETTE) && (pic->bit_depth == 1)) ) dim(2) = 1; if (pic->bit_depth > 1 && pic->bit_depth < 8) pic->bit_depth = 8; NDArray out(dim); dim.resize(2); NDArray alpha(dim); Array<int> coord = Array<int> (3); for (unsigned long j=0; j < pic->height; j++) { coord(0) = j; for (unsigned long i=0; i < pic->width; i++) { coord(1) = i; for (int c = 0; c < out.dims()(2); c++) { coord(2) = c; out(coord) = pic->row_pointers[j][i*4+c]; } alpha(j,i) = pic->row_pointers[j][i*4+3]; } } out = out.squeeze(); switch (pic->bit_depth) { case 1: retval.append((boolNDArray)out); retval.append((boolNDArray)alpha); break; case 8: retval.append((uint8NDArray)out); retval.append((uint8NDArray)alpha); break; case 16: retval.append((uint16NDArray)out); retval.append((uint16NDArray)alpha); break; default: retval.append(out); retval.append(alpha); } delete_canvas(pic); return retval; } canvas *load_canvas(char *filename) { png_structp png_ptr; png_infop info_ptr; FILE *infile = fopen(filename,"rb"); if (!infile) { error("pngread could not open file %s", filename); return NULL; } unsigned char sig[8]; fread(sig,1,8,infile); if (!png_check_sig(sig,8)) { error("pngread invalid signature in %s", filename); fclose(infile); return NULL; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); if (!png_ptr) { error("pngread out of memory"); fclose(infile); return NULL; } info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { error("pngread can't generate info"); png_destroy_read_struct(&png_ptr,NULL,NULL); fclose(infile); return NULL; } /* Set error handling */ if (setjmp(png_jmpbuf(png_ptr))) { error("pngread: libpng exited abnormally"); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(infile); return NULL; } png_init_io(png_ptr, infile); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); png_uint_32 width,height; int color_type, bit_depth; png_get_IHDR(png_ptr,info_ptr,&width,&height, &bit_depth,&color_type,NULL,NULL,NULL); /* Transform grayscale images with depths < 8-bit to 8-bit, change * paletted images to RGB, and add a full alpha channel if there is * transparency information in a tRNS chunk. */ if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); } if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { png_set_gray_1_2_4_to_8(png_ptr); } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { //add alpha png_set_tRNS_to_alpha(png_ptr); } // Always transform image to RGB if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); // If no alpha layer is present, create one if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_RGB) png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER); if (bit_depth < 8) { png_set_packing(png_ptr); } // For now, use 8-bit only if (bit_depth == 16) { png_set_strip_16(png_ptr); } png_read_update_info(png_ptr,info_ptr); // Read the data from the file int stride = png_get_rowbytes(png_ptr, info_ptr); canvas *can = new_canvas(width, height, stride); if (can) { png_read_image(png_ptr, can->row_pointers); } else { error("pngread out of memory"); } png_read_end(png_ptr,NULL); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(infile); // Set color type and depth. Used to determine octave output arguments. can->color_type = color_type; can->bit_depth = bit_depth; return can; }