/*********************************************************************** * decode png file * const char *file_path = path to png file e.g. "/dev_hdd0/test.png" ***********************************************************************/ Buffer load_png(const char *file_path) { Buffer tmp; png_dec_info dec_ctx; // decryption handles void *buf_addr = NULL; // buffer for decoded png data // create png decoder create_decoder(&dec_ctx); // open png stream open_png(&dec_ctx, file_path); // set decode parameter set_dec_param(&dec_ctx); // alloc target buffer buf_addr = mem_alloc(png_w * png_h * 4); // decode png stream, into target buffer decode_png_stream(&dec_ctx, buf_addr); // close png stream PngDecClose(dec_ctx.main_h, dec_ctx.sub_h); // destroy png decoder PngDecDestroy(dec_ctx.main_h); // store png values tmp.addr = (uint32_t*)buf_addr; tmp.w = png_w; tmp.h = png_h; return tmp; }
int res_create_alpha_surface(const char *name, gr_surface *pSurface) { int result = 0; unsigned int y; unsigned char *p_row; gr_surface surface = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; png_byte channels; FILE *fp = NULL; *pSurface = NULL; result = open_png(name, &png_ptr, &info_ptr, &fp, &width, &height, &channels); if (result < 0) return result; if (channels != 1) { result = -7; goto exit; } if (!(surface = malloc_surface(width * height))) { result = -8; goto exit; } surface->width = width; surface->height = height; surface->row_bytes = width; surface->pixel_bytes = 1; for (y = 0; y < height; y++) { p_row = surface->data + y * surface->row_bytes; png_read_row(png_ptr, p_row, NULL); } *pSurface = surface; exit: close_png(&png_ptr, &info_ptr, fp); if (result < 0 && surface != NULL) free(surface); return result; }
int res_create_alpha_surface(const char* name, gr_surface* pSurface) { gr_surface surface = NULL; int result = 0; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; png_byte channels; *pSurface = NULL; result = open_png(name, &png_ptr, &info_ptr, &width, &height, &channels); if (result < 0) return result; if (channels != 1) { result = -7; goto exit; } surface = malloc_surface(width * height); if (surface == NULL) { result = -8; goto exit; } surface->width = width; surface->height = height; surface->row_bytes = width; surface->pixel_bytes = 1; #if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA) png_set_bgr(png_ptr); #endif unsigned char* p_row; unsigned int y; for (y = 0; y < height; ++y) { p_row = surface->data + y * surface->row_bytes; png_read_row(png_ptr, p_row, NULL); } *pSurface = surface; exit: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (result < 0 && surface != NULL) free(surface); return result; }
int res_create_display_surface(const char *name, gr_surface *pSurface) { int result = 0; unsigned int y; unsigned char *p_row; gr_surface surface = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; png_byte channels; FILE *fp = NULL; *pSurface = NULL; result = open_png(name, &png_ptr, &info_ptr, &fp, &width, &height, &channels); if (result < 0) return result; if (!(surface = init_display_surface(width, height))) { result = -8; goto exit; } /* TODO: check for error */ p_row = malloc(width * 4); for (y = 0; y < height; y++) { png_read_row(png_ptr, p_row, NULL); transform_rgb_to_draw(p_row, surface->data + y * surface->row_bytes, channels, width); } free(p_row); *pSurface = surface; exit: close_png(&png_ptr, &info_ptr, fp); if (result < 0 && surface != NULL) free(surface); return result; }
int main (int argc, char *argv[]) { InPng *in_png; char *input_file; char *output_file; if (argc != 3) { fail("usage: stencilizer INPUT-PNG OUTPUT-PNG"); } input_file = argv[1]; output_file = argv[2]; in_png = open_png(input_file); stencilize(in_png, output_file); return 0; }
int res_create_surface_png(const char* name, gr_surface* pSurface) { GGLSurface* surface = NULL; int result = 0; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; png_byte channels; FILE* fp; *pSurface = NULL; result = open_png(name, &png_ptr, &info_ptr, &width, &height, &channels, &fp); if (result < 0) return result; surface = init_display_surface(width, height); if (surface == NULL) { result = -8; goto exit; } unsigned char* p_row = malloc(width * 4); unsigned int y; for (y = 0; y < height; ++y) { png_read_row(png_ptr, p_row, NULL); transform_rgb_to_draw(p_row, surface->data + y * width * 4, channels, width); } free(p_row); if (channels == 3) surface->format = GGL_PIXEL_FORMAT_RGBX_8888; else surface->format = GGL_PIXEL_FORMAT_RGBA_8888; *pSurface = (gr_surface) surface; exit: fclose(fp); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (result < 0 && surface != NULL) free(surface); return result; }
int res_create_display_surface(const char* name, gr_surface* pSurface) { gr_surface surface = NULL; int result = 0; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; png_byte channels; *pSurface = NULL; result = open_png(name, &png_ptr, &info_ptr, &width, &height, &channels); if (result < 0) return result; surface = init_display_surface(width, height); if (surface == NULL) { result = -8; goto exit; } #if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA) png_set_bgr(png_ptr); #endif unsigned char* p_row = malloc(width * 4); unsigned int y; for (y = 0; y < height; ++y) { png_read_row(png_ptr, p_row, NULL); transform_rgb_to_draw(p_row, surface->data + y * surface->row_bytes, channels, width); } free(p_row); *pSurface = surface; exit: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (result < 0 && surface != NULL) free(surface); return result; }
/*********************************************************************** * Method : Image::read_png * Params : char *file_name * Returns: int (success/failure) * Effects: opens file, reads data into memory (if it is a png file) ***********************************************************************/ int Image::read_png(char *file) { // reset and free up memory: clear(); FILE *fp = open_png(file); if (!fp) return 0; png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { fclose(fp); fprintf(stderr,"Image::read_png: png_create_read_struct() failed"); return 0; } // Allocate/initialize the memory for image information png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fclose(fp); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fprintf(stderr,"Image::read_png: png_create_info_struct() failed"); return 0; } // Set error handling if (setjmp(png_ptr->jmpbuf)) { // jump here from error encountered inside PNG code... // free all memory associated with the png_ptr and info_ptr png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fp); fprintf(stderr,"Image::read_png: error reading file %s", file); clear(); return 0; } // Set up the input control (using standard C streams) // png_init_io(png_ptr, fp); // indicate how much of the file has been read: png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); // read information from the file before the first image data chunk png_read_info(png_ptr, info_ptr); // extract _width, _height, and other info from header: int bit_depth, color_type, interlace_type; png_get_IHDR(png_ptr, info_ptr, (unsigned long*)&_width, (unsigned long*)&_height, &bit_depth, &color_type, &interlace_type, NULL, NULL); // tell libpng to strip 16 bit/color files down to 8 bits/channel png_set_strip_16(png_ptr); // Extract multiple pixels with bit depths of 1, 2, and 4 from a single // byte into separate bytes (useful for paletted and grayscale images). png_set_packing(png_ptr); // Expand paletted colors into true RGB triplets if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); // Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand(png_ptr); // Expand paletted or RGB images with transparency to full alpha channels // so the data will be available as RGBA quartets. if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); // update the header to reflect transformations applied: png_read_update_info(png_ptr, info_ptr); // now it's safe to read the size of a row: unsigned long row_bytes = png_get_rowbytes(png_ptr, info_ptr); _bpp = row_bytes / _width; // make sure bytes per pixel is a valid number: if (_bpp < 1 || _bpp > 4) { fprintf(stderr,"Image::read_png: %d bytes/pixel not supported", _bpp); } else if (interlace_type != PNG_INTERLACE_NONE) { fprintf(stderr,"Image::read_png: unsupported interlace type (%d)", interlace_type); } else if ((_data = new uchar [ size() ]) == 0) { fprintf(stderr,"Image::read_png: can't allocate data"); } else { _no_delete = 0; // no more excuses: read the image (inverted vertically): for (int y=_height-1; y>=0; y--) png_read_row(png_ptr, _data + y*row_bytes, 0); // read rest of file, and get additional // chunks in info_ptr - REQUIRED png_read_end(png_ptr, info_ptr); } // clean up after the read, and free any memory allocated - REQUIRED png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); // close the file fclose(fp); // return pixel data: if (_data) return 1; else { clear(); return 0; } }
/* * Parameters: <hundred_dpi> <basename_> <titlestring> <bottom_html_code> * <pageoffset> [first page number] */ int main(int argc, char **argv) { int a,z; if (argc<7){ fprintf(stderr,"Usage: pbm2png <hundred_dpi> <basename_> <titlestring> <bottom_html_code> <pageoffset> <ifname> [starting_filenumber]\n"); return 0; } dpi=atof(argv[1])/10; ppm=dpi*1000/25.4; basename_=argv[2]; titlestring=argv[3]; bottom=argv[4]; pageoffset=atol(argv[5]); filename=argv[6]; again0: ifd=open(filename,O_RDONLY); if (ifd<0){ if (errno==EAGAIN||errno==EINTR||errno==EWOULDBLOCK) goto again0; else { perror(""); exit(1); } } fprintf(stderr,"filename %s, %d\n",filename,ifd); if (argc>=8){ filenumber=atol(argv[7]); } gentables(); again: fprintf(stderr,"\nFile %i\n",filenumber); if (read_header()){ for (a=0;a<filenumber;a++) make_page(a); make_index(); return 0; } lw=(x+15)>>4; lb=(x+7)>>3; ox=x/17; oy=y/15; fprintf(stderr,"Input: %i*%i pixels, %f*%f dpi, %.1fMB.\n",x,y,dpi*17,dpi*15,(float)lb*y/1048576); fprintf(stderr,"Ouput: %i*%i pixels, %f*%f dpi, %.1fKB raw data.\n",ox,oy,dpi,dpi,(float)ox*oy/1024); l1=(unsigned char*)malloc(lw*2); l2=(unsigned long*)malloc(lw*sizeof(unsigned long)); l4=(unsigned long long*)malloc(lw*sizeof(unsigned long long)); sprintf(string,"%s%d.png",basename_,filenumber); filenumber++; of=fopen(string,"w"); open_png(); for (z=oy;z;z--){ if (!(z&15)){ fprintf(stderr,"."); fflush(stderr); } load_to_4(); export_from_4(); } close_png(); fprintf(stderr,"\nWritten %lu bytes of data, ratio %.1f%%\n",ftell(of),(float)ftell(of)*100/ox/oy); fclose(of); for (a=y%15;a;a--) load(); free(l1); free(l2); free(l4); goto again; }
image_t *load_png(char *png) { int width = 0; int height = 0; FILE *f = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_infop end_info = NULL; png_uint_32 rowbytes = 0; image_t *image = NULL; f = open_png(png); if (f == NULL) goto err; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, NULL, NULL); if (!png_ptr) goto err; info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) goto err; end_info = png_create_info_struct(png_ptr); if (!end_info) goto err; if (setjmp(png_jmpbuf(png_ptr))) { printf("[read_png_file] Error during read_image"); goto err; } png_init_io(png_ptr, f); png_set_sig_bytes(png_ptr, HEADER_SIZE); png_read_info(png_ptr, info_ptr); rowbytes = png_get_rowbytes(png_ptr, info_ptr); width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); if (png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGBA) { printf("Error: PNG format is not RGBA\n"); goto err; } if (setjmp(png_jmpbuf(png_ptr))) { printf("[read_png_file] Error during read_image"); goto err; } image = make_image(width, height, rowbytes); if (image == NULL) goto err; png_read_image(png_ptr, image->rows); png_read_end(png_ptr, end_info); done: if (f != NULL) fclose(f); if (png_ptr != NULL) png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return image; err: free_image(image); image = NULL; goto done; }
int res_create_multi_display_surface(const char* name, int* frames, gr_surface** pSurface) { gr_surface* surface = NULL; int result = 0; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; png_byte channels; int i; *pSurface = NULL; *frames = -1; result = open_png(name, &png_ptr, &info_ptr, &width, &height, &channels); if (result < 0) return result; *frames = 1; png_textp text; int num_text; if (png_get_text(png_ptr, info_ptr, &text, &num_text)) { for (i = 0; i < num_text; ++i) { if (text[i].key && strcmp(text[i].key, "Frames") == 0 && text[i].text) { *frames = atoi(text[i].text); break; } } printf(" found frames = %d\n", *frames); } if (height % *frames != 0) { printf("bad height (%d) for frame count (%d)\n", height, *frames); result = -9; goto exit; } surface = malloc(*frames * sizeof(gr_surface)); if (surface == NULL) { result = -8; goto exit; } for (i = 0; i < *frames; ++i) { surface[i] = NULL;//init_display_surface(width, height / *frames); if (surface[i] == NULL) { result = -8; goto exit; } } /*unsigned char* p_row = malloc(width * 4); unsigned int y; for (y = 0; y < height; ++y) { png_read_row(png_ptr, p_row, NULL); int frame = y % *frames; unsigned char* out_row = surface[frame]->data + (y / *frames) * surface[frame]->row_bytes; transform_rgb_to_draw(p_row, out_row, channels, width); } free(p_row); this will need to be brought in line with the older resources and graphics code */ *pSurface = (gr_surface*) surface; exit: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (result < 0) { if (surface) { for (i = 0; i < *frames; ++i) { if (surface[i]) free(surface[i]); } free(surface); } } return result; }
int main(int argc, char **argv) { // Handle command line arguments prog_options p; parse_options(&p,argc,argv); validate_options(&p); // Return value int r; // Init library r = png_init(0, 0); // Read current image png_file pf_current; png_file pf_previous; // Find motion if ( p.file_out != NULL ) { // Run until signal trap is reached signal(SIGINT, &trap); execute = 1; while(execute){ if(p.verbose || p.debug) fprintf(stdout,"\nNew round\n"); if(p.verbose || p.debug) gettimeofday(&tv1_total, NULL); // Read current image if(p.debug) gettimeofday(&tv1, NULL); r = open_png(&pf_current, p.file_current); png_write_error(r); if( r >= PNG_NO_ERROR ) { // Read "previous" image if( pf_previous.is_open != 1 ) { r = open_png(&pf_previous, p.file_current); png_write_error(r); } // Image instance from png motion_image image_current; image_from_png_data (&image_current, pf_current.data, pf_current.png_obj.width, pf_current.png_obj.height); motion_image image_previous; image_from_png_data (&image_previous, pf_previous.data, pf_current.png_obj.width, pf_current.png_obj.height); if(p.debug) gettimeofday(&tv2, NULL); if(p.debug) printf ("Open file:\t\t%f seconds\n", get_timediff(&tv1,&tv2)); // Noise reduction if(p.debug) gettimeofday(&tv1, NULL); filter_noise_reduction (&(image_current.average),1); filter_noise_reduction (&(image_previous.average),1); if(p.debug) gettimeofday(&tv2, NULL); if(p.debug) printf ("Noise reduction:\t%f seconds\n", get_timediff(&tv1,&tv2)); // Intensity correction if(p.debug) gettimeofday(&tv1, NULL); int intensity_current = get_average_intensity(&(image_current.average)); int intensity_previous = get_average_intensity(&(image_previous.average)); int intensity_difference_before = (intensity_current - intensity_previous) / 2; filter_adjust_intensity (&(image_current.average),-intensity_difference_before); filter_adjust_intensity (&(image_previous.average),intensity_difference_before); if(p.debug) gettimeofday(&tv2, NULL); if(p.debug) printf ("Intensity correction:\t%f seconds\n", get_timediff(&tv1,&tv2)); // Background subtraction if(p.debug) gettimeofday(&tv1, NULL); filter_background_subtraction(&(image_current.average),&(image_previous.average)); if(p.debug) gettimeofday(&tv2, NULL); if(p.debug) printf ("Background subtraction:\t%f seconds\n", get_timediff(&tv1,&tv2)); // Binary split if(p.debug) gettimeofday(&tv1, NULL); filter_split_binary(&(image_current.average),p.sensitivity); if(p.debug) gettimeofday(&tv2, NULL); if(p.debug) printf ("Binary split:\t\t%f seconds\n", get_timediff(&tv1,&tv2)); // Blob reduction if(p.debug) gettimeofday(&tv1, NULL); int pixels_left = filter_reduce_blobs(&(image_current.average),p.passes); if(p.debug) gettimeofday(&tv2, NULL); if(p.debug) printf ("Blob reduction:\t\t%f seconds\n", get_timediff(&tv1,&tv2)); if(p.verbose || p.debug) printf ("Pixels left:\t\t%i/10\n", pixels_left); if( pixels_left >= 10 ) { // Save file if(p.debug) gettimeofday(&tv1, NULL); // ToDo: Delegate file saving to thread char * filename = format_time(p.file_out); png_save_file(&pf_current,format_time(p.file_out)); free(filename); if(p.debug) gettimeofday(&tv2, NULL); if(p.debug) printf ("File save:\t\t%f seconds\n", get_timediff(&tv1,&tv2)); } // png_close_file(&pf_current.png_obj); // pf_current is closed as pf_previous on signal png_close_file(&pf_previous.png_obj); free(pf_previous.data); pf_previous = pf_current; free_image(image_current); free_image(image_previous); if(p.verbose || p.debug) gettimeofday(&tv2_total, NULL); if(p.verbose || p.debug) printf ("Total round time:\t%f seconds\n", get_timediff(&tv1_total,&tv2_total)); } else { pf_previous.is_open = 0; png_close_file(&pf_previous.png_obj); free(pf_previous.data); pf_previous.data = NULL; } } if(p.verbose || p.debug) printf ("\nExecution interrupted, cleaning up...\n"); r = png_close_file(&pf_previous.png_obj); free(pf_previous.data); signal(SIGINT, SIG_DFL); } // Find difference if ( p.file_out_difference != NULL ) { // Fixme: Move calculation to motion.c int change_treshold = 10; int x, y; for( x = 0 ; x < pf_current.png_obj.width ; x++ ) { for( y = 0 ; y < pf_current.png_obj.height ; y++ ) { int pixel_idx = (pf_current.png_obj.width*y*4+x*4); // Check for changes on pixel level int avg_new = (pf_current.data[pixel_idx]+pf_current.data[pixel_idx+1]+pf_current.data[pixel_idx+2])/3; int avg_old = (pf_previous.data[pixel_idx]+pf_previous.data[pixel_idx+1]+pf_previous.data[pixel_idx+2])/3; int difference = (avg_new - avg_old); if(!( abs(pf_current.data[pixel_idx]-pf_previous.data[pixel_idx]) > change_treshold || abs(pf_current.data[pixel_idx+1]-pf_previous.data[pixel_idx+1]) > change_treshold || abs(pf_current.data[pixel_idx+2]-pf_previous.data[pixel_idx+2]) > change_treshold || abs(difference) > change_treshold )) { pf_current.data[pixel_idx] = 0; pf_current.data[pixel_idx+1] = 0; pf_current.data[pixel_idx+2] = 0; pf_current.data[pixel_idx+3] = 0; } } } // Save difference png_save_file(&pf_current,p.file_out_difference); // Output file old r = png_close_file(&pf_current.png_obj); r = png_close_file(&pf_previous.png_obj); free(pf_current.data); free(pf_previous.data); } exit(EXIT_SUCCESS); }
int res_create_localized_alpha_surface(const char* name, const char* locale, gr_surface* pSurface) { gr_surface surface = NULL; int result = 0; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; png_byte channels; *pSurface = NULL; if (locale == NULL) { surface = malloc_surface(0); surface->width = 0; surface->height = 0; surface->row_bytes = 0; surface->pixel_bytes = 1; goto exit; } result = open_png(name, &png_ptr, &info_ptr, &width, &height, &channels); if (result < 0) return result; if (channels != 1) { result = -7; goto exit; } unsigned char* row = malloc(width); png_uint_32 y; for (y = 0; y < height; ++y) { png_read_row(png_ptr, row, NULL); int w = (row[1] << 8) | row[0]; int h = (row[3] << 8) | row[2]; int len = row[4]; char* loc = (char*)row+5; if (y+1+h >= height || matches_locale(loc, locale)) { printf(" %20s: %s (%d x %d @ %d)\n", name, loc, w, h, y); surface = malloc_surface(w*h); if (surface == NULL) { result = -8; goto exit; } surface->width = w; surface->height = h; surface->row_bytes = w; surface->pixel_bytes = 1; int i; for (i = 0; i < h; ++i, ++y) { png_read_row(png_ptr, row, NULL); memcpy(surface->data + i*w, row, w); } *pSurface = (gr_surface) surface; break; } else { int i; for (i = 0; i < h; ++i, ++y) { png_read_row(png_ptr, row, NULL); } } } exit: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (result < 0 && surface != NULL) free(surface); return result; }
int res_create_localized_alpha_surface(const char *name, const char *locale, gr_surface *pSurface) { int result = 0; unsigned char *row; gr_surface surface = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height, y; png_byte channels; FILE *fp = NULL; *pSurface = NULL; if (!locale) { surface = malloc_surface(0); surface->width = 0; surface->height = 0; surface->row_bytes = 0; surface->pixel_bytes = 1; goto exit; } result = open_png(name, &png_ptr, &info_ptr, &fp, &width, &height, &channels); if (result < 0) return result; if (channels != 1) { result = -7; goto exit; } /* TODO: check for error */ row = malloc(width); for (y = 0; y < height; y++) { int h, w; char *loc; png_read_row(png_ptr, row, NULL); w = (row[1] << 8) | row[0]; h = (row[3] << 8) | row[2]; loc = (char *)row + 5; if (y + 1 + h >= height || matches_locale(loc, locale)) { int i; printf(" %20s: %s (%d x %d @ %ld)\n", name, loc, w, h, (long)y); if (!(surface = malloc_surface(w * h))) { result = -8; goto exit; } surface->width = w; surface->height = h; surface->row_bytes = w; surface->pixel_bytes = 1; for (i = 0; i < h; i++, y++) { png_read_row(png_ptr, row, NULL); memcpy(surface->data + i * w, row, w); } *pSurface = (gr_surface)surface; break; } else { int i; for (i = 0; i < h; i++, y++) png_read_row(png_ptr, row, NULL); } } exit: close_png(&png_ptr, &info_ptr, fp); if (result < 0 && surface) free(surface); return result; }
int res_create_multi_display_surface(const char *name, int *frames, gr_surface **pSurface) { int i, result = 0, num_text; unsigned int y; unsigned char *p_row; gr_surface *surface = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; png_byte channels = 0; png_textp text; FILE *fp = NULL; *pSurface = NULL; *frames = -1; result = open_png(name, &png_ptr, &info_ptr, &fp, &width, &height, &channels); if (result < 0) return result; *frames = 1; if (png_get_text(png_ptr, info_ptr, &text, &num_text)) { for (i = 0; i < num_text; i++) if (text[i].key && !strcmp(text[i].key, "Frames") && text[i].text) { *frames = atoi(text[i].text); break; } printf(" found frames = %d\n", *frames); } if (height % *frames != 0) { printf("bad height (%ld) for frame count (%d)\n", (long)height, *frames); result = -9; goto exit; } if (!(surface = malloc(*frames * sizeof(gr_surface)))) { result = -8; goto exit; } for (i = 0; i < *frames; i++) { surface[i] = init_display_surface(width, height / *frames); if (!surface[i]) { result = -8; goto exit; } } /* TODO: Check for error */ p_row = malloc(width * 4); for (y = 0; y < height; y++) { int frame = y % *frames; unsigned char *out_row; png_read_row(png_ptr, p_row, NULL); out_row = surface[frame]->data + (y / *frames) * surface[frame]->row_bytes; transform_rgb_to_draw(p_row, out_row, channels, width); } free(p_row); *pSurface = (gr_surface *)surface; exit: close_png(&png_ptr, &info_ptr, fp); if (result < 0) if (surface) { for (i = 0; i < *frames; i++) if (surface[i]) free(surface[i]); free(surface); } return result; }