png.c
上传用户:hengzhunsh
上传日期:2013-09-07
资源大小:19k
文件大小:5k
- /*
- fbv -- simple image viewer for the linux framebuffer
- Copyright (C) 2000, 2001, 2003 Mateusz Golicz
- 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 "config.h"
- #ifdef FBV_SUPPORT_PNG
- #include <png.h>
- #include "fbv.h"
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
- #define PNG_BYTES_TO_CHECK 4
- #ifndef min
- #define min(x,y) ((x) < (y) ? (x) : (y))
- #endif
- int fh_png_id(char *name)
- {
- int fd;
- char id[4];
- fd=open(name,O_RDONLY); if(fd==-1) return(0);
- read(fd,id,4);
- close(fd);
- if(id[1]=='P' && id[2]=='N' && id[3]=='G') return(1);
- return(0);
- }
-
- int fh_png_load(char *name,unsigned char *buffer, unsigned char ** alpha,int x,int y)
- {
- png_structp png_ptr;
- png_infop info_ptr;
- png_uint_32 width, height;
- int i;
- int bit_depth, color_type, interlace_type;
- int number_passes,pass, trans = 0;
- char *rp;
- png_bytep rptr[2];
- char *fbptr;
- FILE *fh;
- if(!(fh=fopen(name,"rb"))) return(FH_ERROR_FILE);
- png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
- if (png_ptr == NULL) return(FH_ERROR_FORMAT);
- info_ptr = png_create_info_struct(png_ptr);
- if (info_ptr == NULL)
- {
- png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
- fclose(fh); return(FH_ERROR_FORMAT);
- }
- rp=0;
- if (setjmp(png_ptr->jmpbuf))
- {
- png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
- if(rp) free(rp);
- fclose(fh); return(FH_ERROR_FORMAT);
- }
- png_init_io(png_ptr,fh);
- png_read_info(png_ptr, info_ptr);
- png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,&interlace_type, NULL, NULL);
- if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr);
- if (bit_depth < 8) png_set_packing(png_ptr);
- if (color_type == PNG_COLOR_TYPE_GRAY || color_type== PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr);
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
- {
- trans = 1;
- png_set_tRNS_to_alpha(png_ptr);
- }
- if(bit_depth == 16) png_set_strip_16(png_ptr);
- number_passes = png_set_interlace_handling(png_ptr);
- png_read_update_info(png_ptr,info_ptr);
- if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA || color_type == PNG_COLOR_TYPE_RGB_ALPHA || trans)
- {
- unsigned char * alpha_buffer = (unsigned char*) malloc(width * height);
- unsigned char * aptr;
-
- rp = (char*) malloc(width * 4);
- rptr[0] = (png_bytep) rp;
-
- *alpha = alpha_buffer;
-
- for (pass = 0; pass < number_passes; pass++)
- {
- fbptr = buffer;
- aptr = alpha_buffer;
-
- for(i=0; i<height; i++)
- {
- int n;
- unsigned char *trp = rp;
-
- png_read_rows(png_ptr, rptr, NULL, 1);
-
- for(n = 0; n < width; n++, fbptr += 3, trp += 4)
- {
- memcpy(fbptr, trp, 3);
- *(aptr++) = trp[3];
- }
- }
- }
- free(rp);
- }
- else
- {
- for (pass = 0; pass < number_passes; pass++)
- {
- fbptr = buffer;
- for(i=0; i<height; i++, fbptr += width*3)
- {
- rptr[0] = (png_bytep) fbptr;
- png_read_rows(png_ptr, rptr, NULL, 1);
- }
- }
- }
- png_read_end(png_ptr, info_ptr);
- png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
- fclose(fh);
- return(FH_ERROR_OK);
- }
- int fh_png_getsize(char *name,int *x,int *y)
- {
- png_structp png_ptr;
- png_infop info_ptr;
- png_uint_32 width, height;
- int bit_depth, color_type, interlace_type;
- char *rp;
- FILE *fh;
- if(!(fh=fopen(name,"rb"))) return(FH_ERROR_FILE);
- png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
- if (png_ptr == NULL) return(FH_ERROR_FORMAT);
- info_ptr = png_create_info_struct(png_ptr);
- if (info_ptr == NULL)
- {
- png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
- fclose(fh); return(FH_ERROR_FORMAT);
- }
- rp=0;
- if (setjmp(png_ptr->jmpbuf))
- {
- png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
- if(rp) free(rp);
- fclose(fh); return(FH_ERROR_FORMAT);
- }
-
- png_init_io(png_ptr,fh);
- png_read_info(png_ptr, info_ptr);
- png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,&interlace_type, NULL, NULL);
- png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
- *x=width;
- *y=height;
- fclose(fh);
- return(FH_ERROR_OK);
- }
- #endif