c++ - how to correctly use libpng -


edit: i'm using libpng 1.6 on windows 7

i'm convinced usage of libpng causing memory leak (edit: confirmed) loading images using function causes spike in memory when unload images , reload them memory usage sky rockets. instead of being few meg in memory app using hundreds. i'm unable see problem code, i've done best free resources. i'd second opinion memory leak didn't exist when using different method load textures.

here function:

#define png_sig_bytes (8) /* bytes in png file signature. */ gluint loadpngtexturergba(const string filename, int &width, int &height) {     file* fp = null; #ifdef __linux__     fp = fopen(filename.c_str(), "rb"); #elif defined(_win32)     fopen_s(&fp, filename.c_str(), "rb"); #endif     if (fp == null)     { #ifdef __linux         std::cout << "unable load png texture file" << std::endl; #else         messagebox(0, l"unable load texture", l"error", mb_ok);         exit(0); #endif     }      png_byte magic[png_sig_bytes]; /* (signature byte buffer) */      png_structp png_ctx;     png_infop info_ctx;      png_uint_32 img_width, img_height, row;     png_byte img_depth, img_color_type;      /* 'volatile' qualifier forces reload in setjmp cleanup: */      png_byte *volatile img_data = null;     png_bytep *volatile row_data = null;      ;//*buf = null;        /* assumed 'longjmp' can invoked within      * code efficiently unwind resources *all* errors. */       /* png structures , resource unwinding: */      if ((png_ctx = png_create_read_struct(         png_libpng_ver_string, null, null, null)) == null)         return (1); /* enomem (?) */      if ((info_ctx = png_create_info_struct(png_ctx)) == null)     {         png_destroy_read_struct(&png_ctx, null, null);         return (1); /* enomem (?) */     }      if (setjmp(png_jmpbuf(png_ctx)) != 0)     {         png_destroy_read_struct(&png_ctx, &info_ctx, null);         free(img_data); free(row_data);          return (1); /* libpng feedback (?) */     }      /* check png file signature: */      if (fread(magic, (1), png_sig_bytes, fp) != png_sig_bytes)         png_error(png_ctx, "invalid png file");      if (png_sig_cmp(magic, 0, png_sig_bytes))         png_error(png_ctx, "invalid png file");       /* set input file stream , png image info: */      png_init_io(png_ctx, fp);     png_set_sig_bytes(png_ctx, png_sig_bytes);      png_read_info(png_ctx, info_ctx);      img_width = png_get_image_width(png_ctx, info_ctx);     img_height = png_get_image_height(png_ctx, info_ctx);  #if (1) /* png doesn't support 0 area image? */      if (img_width == 0 || img_height == 0)         png_error(png_ctx, "zero area png image"); #endif      if (png_rgba_pixel_limit2(img_width, img_height))         png_error(png_ctx, "png image exceeds pixel limits");      img_depth = png_get_bit_depth(png_ctx, info_ctx);     img_color_type = png_get_color_type(png_ctx, info_ctx);      /* ignored image interlacing, compression , filtering. */      /* force 8-bit color channels: */      if (img_depth == 16)         png_set_strip_16(png_ctx);      else if (img_depth < 8)         png_set_packing(png_ctx);      /* force formats rgb: */      if (img_color_type != png_color_type_rgba)         png_set_expand(png_ctx);      if (img_color_type == png_color_type_palette)         png_set_palette_to_rgb(png_ctx);      if (img_color_type == png_color_type_gray)         png_set_gray_to_rgb(png_ctx);      if (img_color_type == png_color_type_gray_alpha)         png_set_gray_to_rgb(png_ctx);      /* add full opacity alpha channel if required: */      if (img_color_type != png_color_type_rgba)         png_set_filler(png_ctx, 0xff, png_filler_after);      /* apply output transforms before reading image data: */      png_read_update_info(png_ctx, info_ctx);       /* allocate rgba image data: */      img_data = (png_byte *)         malloc((size_t)(img_width * img_height * (4)));      if (img_data == null)         png_error(png_ctx, "error allocating image buffer");      /* allocate row pointers: */      row_data = (png_bytep *)         malloc((size_t)(img_height * sizeof(png_bytep)));      if (row_data == null)         png_error(png_ctx, "error allocating row pointers");      /* set row pointers , read rgba image data: */      (row = 0; row < img_height; row++)         row_data[row] = img_data +         (img_height - (row + 1)) * (img_width * (4));      png_read_image(png_ctx, row_data);      /* libpng , dynamic resource unwinding: */      png_read_end(png_ctx, null);     png_destroy_info_struct(png_ctx, (png_infopp)&info_ctx);                png_destroy_read_struct(&png_ctx, &info_ctx, (png_infopp)null);      free(row_data);      //*w = (unsigned) img_width, *h = (unsigned) img_height;     width = img_width;     height = img_height;     //*buf = img_data; /* (asserts png_byte unsigned char) */      //now generate opengl texture object     gluint texture;     glgentextures(1, &texture);     glbindtexture(gl_texture_2d, texture);     glpixelstorei(gl_unpack_alignment, 1); // important!                                             // manual mip map attempt?                                            //gltexparameteri(gl_texture_2d, gl_texture_base_level, 0);                                            //gltexparameteri(gl_texture_2d, gl_texture_max_level, 0);      glteximage2d(gl_texture_2d, 0, gl_rgba, width, height, 0,         gl_rgba, gl_unsigned_byte, (glvoid*)img_data);      bool auto_mipmap = true;     if (dqoi_mipmaps_disabled)         auto_mipmap = false;     if (auto_mipmap)     {         glgeneratemipmap(gl_texture_2d);  //generate num_mipmaps number of mipmaps here.         gltexparameteri(gl_texture_2d, gl_texture_wrap_s, gl_repeat);         gltexparameteri(gl_texture_2d, gl_texture_wrap_t, gl_repeat);         gltexparameteri(gl_texture_2d, gl_texture_mag_filter, gl_linear);         gltexparameteri(gl_texture_2d, gl_texture_min_filter, gl_linear_mipmap_linear);     }     else     {         gltexparameteri(gl_texture_2d, gl_texture_wrap_s, gl_repeat);         gltexparameteri(gl_texture_2d, gl_texture_wrap_t, gl_repeat);          gltexparameteri(gl_texture_2d, gl_texture_min_filter, gl_nearest);         gltexparameterf(gl_texture_2d, gl_texture_mag_filter, gl_linear);      }      fclose(fp);      free(img_data);      return texture; } 

edit: second revision, still have same problem

gluint loadpngtexturergba(const string filename, int &width, int &height) {     png_byte header[png_sig_bytes];      file *fp = null; #ifdef __linux__     fp = fopen(filename.c_str(), "rb"); #elif defined(_win32)     fopen_s(&fp, filename.c_str(), "rb"); #endif      if (!fp)     { #ifdef __linux         std::cout << "unable load png texture file" << std::endl; #else         messagebox(0, l"unable load texture", l"error", mb_ok); #endif         return texture_load_error; }      if (fread(header, 1, png_sig_bytes, fp) != png_sig_bytes)     {         fclose(fp);         //png_error(header, "invalid png file");         return texture_load_error;     }      //test if png     int is_png = !png_sig_cmp(header, 0, 8);     if (!is_png) {         fclose(fp);         return texture_load_error;     }      /* png structures , resource unwinding: */     png_structp png_ptr;     if ((png_ptr = png_create_read_struct(png_libpng_ver_string, null, null, null)) == null)     {         fclose(fp);         return texture_load_error; /* enomem (?) */     }      png_infop info_ptr;     if (!(info_ptr = png_create_info_struct(png_ptr)))     {         png_destroy_read_struct(&png_ptr, (png_infopp)null, (png_infopp)null);         fclose(fp);         return texture_load_error; /* enomem (?) */     }      //create png info struct     png_infop end_info = png_create_info_struct(png_ptr);     if (!end_info) {         png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)null);         fclose(fp);         return (texture_load_error);     }      /* assumed 'longjmp' can invoked within     * code efficiently unwind resources *all* errors. */      png_byte *image_data = null;     png_bytep *row_pointers = null;      if (setjmp(png_jmpbuf(png_ptr)) != 0)     {         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);          delete[] image_data;         delete[] row_pointers;          fclose(fp);         return (texture_load_error);     }      //init png reading     png_init_io(png_ptr, fp);      //let libpng know read first 8 bytes     png_set_sig_bytes(png_ptr, 8);      // read info image data     png_read_info(png_ptr, info_ptr);      //variables pass info     int bit_depth, color_type;     png_uint_32 twidth, theight;      // info png     png_get_ihdr(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type,         null, null, null);      //update width , height based on png info     width = twidth;     height = theight;      if (width == 0 || height == 0)         png_error(png_ptr, "zero area png image");      if (png_rgba_pixel_limit2(width, height))         png_error(png_ptr, "png image exceeds pixel limits");      /* force 8-bit color channels: */      if (bit_depth == 16)         png_set_strip_16(png_ptr);      else if (bit_depth < 8)         png_set_packing(png_ptr);       /* force formats rgb: */      if (color_type != png_color_type_rgba)         png_set_expand(png_ptr);      if (color_type == png_color_type_palette)         png_set_palette_to_rgb(png_ptr);      if (color_type == png_color_type_gray)         png_set_gray_to_rgb(png_ptr);      if (color_type == png_color_type_gray_alpha)         png_set_gray_to_rgb(png_ptr);      /* add full opacity alpha channel if required: */      if (color_type != png_color_type_rgba)         png_set_filler(png_ptr, 0xff, png_filler_after);      // update png info struct.     png_read_update_info(png_ptr, info_ptr);      // row size in bytes.     int rowbytes = png_get_rowbytes(png_ptr, info_ptr);      // allocate image_data big block, given opengl     image_data = new png_byte[rowbytes * height];     if (!image_data) {         //clean memory , close stuff         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);         fclose(fp);         return texture_load_error;     }      //row_pointers pointing image_data reading png libpng     row_pointers = new png_bytep[height];     if (!row_pointers) {         //clean memory , close stuff         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);         delete[] image_data;         fclose(fp);         return texture_load_error;     }     // set individual row_pointers point @ correct offsets of image_data     (int = 0; < height; ++i)         row_pointers[height - 1 - i] = image_data + * rowbytes;      //read png image_data through row_pointers     png_read_image(png_ptr, row_pointers);      //now generate opengl texture object     gluint texture;     glgentextures(1, &texture);     glbindtexture(gl_texture_2d, texture);     glpixelstorei(gl_unpack_alignment, 1); // important!       bool auto_mipmap = true;     if (dqoi_mipmaps_disabled)         auto_mipmap = false;     if (auto_mipmap)     {         glgeneratemipmap(gl_texture_2d);  //generate num_mipmaps number of mipmaps here.         gltexparameteri(gl_texture_2d, gl_texture_wrap_s, gl_repeat);         gltexparameteri(gl_texture_2d, gl_texture_wrap_t, gl_repeat);         gltexparameteri(gl_texture_2d, gl_texture_mag_filter, gl_linear);         gltexparameteri(gl_texture_2d, gl_texture_min_filter, gl_linear_mipmap_linear);     }     else     {         gltexparameteri(gl_texture_2d, gl_texture_wrap_s, gl_repeat);         gltexparameteri(gl_texture_2d, gl_texture_wrap_t, gl_repeat);          // default //         gltexparameteri(gl_texture_2d, gl_texture_min_filter, gl_nearest);         gltexparameterf(gl_texture_2d, gl_texture_mag_filter, gl_linear);         // default //          // gltexparameteri(gl_texture_2d, gl_texture_mag_filter, gl_nearest);         //gltexparameteri(gl_texture_2d, gl_texture_min_filter, gl_nearest);     }      glteximage2d(gl_texture_2d, 0, gl_rgba, width, height, 0,         gl_rgba, gl_unsigned_byte, (glvoid*)image_data);      //clean memory , close stuff     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);     delete[] image_data;     delete[] row_pointers;      fclose(fp);      return texture;  } 


Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -