iphone - CreateARGBBitmapContext causing memory leak -


i'm using below code create similar effect coreimage's cicircularwrap filter not available ios. here's code causing memory leak. i've released context image creates. life of me, can't spot leak. input appreciated. thanks.

here's how method called:

uiimage *circularwrapimage = [uiimage imagewithcgimage:circularwrap(image.cgimage, 0, 1000, 0, yes, yes)]; 

actual method:

cgcontextref createargbbitmapcontext (size_t pixelswide, size_t pixelshigh){ cgcontextref    context = null; cgcolorspaceref colorspace; void *          bitmapdata; int             bitmapbytecount; int             bitmapbytesperrow;  // declare number of bytes per row. each pixel in bitmap in // example represented 4 bytes; 8 bits each of red, green, blue, , // alpha. bitmapbytesperrow   = (int)(pixelswide * 4); bitmapbytecount     = (int)(bitmapbytesperrow * pixelshigh);  // use generic rgb color space. colorspace = cgcolorspacecreatedevicergb(); if (colorspace == null) {     fprintf(stderr, "error allocating color space\n");     return null; }  // allocate memory image data. destination in memory // drawing bitmap context rendered. bitmapdata = malloc( bitmapbytecount ); if (bitmapdata == null) {     fprintf (stderr, "memory not allocated!");     cgcolorspacerelease( colorspace );     return null; }  // create bitmap context. want pre-multiplied argb, 8-bits // per component. regardless of source image format // (cmyk, grayscale, , on) converted on format // specified here cgbitmapcontextcreate. context = cgbitmapcontextcreate (bitmapdata,                                  pixelswide,                                  pixelshigh,                                  8,      // bits per component                                  bitmapbytesperrow,                                  colorspace,                                  kcgimagealphapremultipliedfirst); if (context == null) {     free (bitmapdata);     fprintf (stderr, "context not created!"); }  // make sure , release colorspace before returning cgcolorspacerelease( colorspace );  return context;  cgcontextrelease(context);}  cgimageref circularwrap3(cgimageref inimage,cgfloat bottomradius, cgfloat topradius, cgfloat startangle, bool clockwise, bool interpolate){ //if(topradius < 0 || bottomradius < 0) return null;  // create bitmap context int w = (int)cgimagegetwidth(inimage); int h = (int)cgimagegetheight(inimage);  //result image side size (always square image) int resultside = 2*max(topradius, bottomradius); cgcontextref cgctx1 = createargbbitmapcontext(w,h); cgcontextref cgctx2 = createargbbitmapcontext(resultside,resultside);  if (cgctx1 == null || cgctx2 == null) {     return null; }  // image width, height. we'll use entire image. cgrect rect = {{0,0},{w,h}};  // draw image bitmap context. once draw, memory // allocated context rendering contain // raw image data in specified color space. cgcontextdrawimage(cgctx1, rect, inimage);  // can pointer image data associated bitmap // context. int *data1 = cgbitmapcontextgetdata (cgctx1); int *data2 = cgbitmapcontextgetdata (cgctx2);  int resultimagesize = resultside*resultside; double temp; for(int *p = data2, pos = 0;pos<resultimagesize;p++,pos++) {     *p = 0;     int x = pos%resultside-resultside/2;     int y = -pos/resultside+resultside/2;     cgfloat phi = modf(((atan2(x, y)+startangle)/2.0/m_pi+0.48),&temp);     if(!clockwise) phi = 1-phi;     phi*=w;     cgfloat r = ((sqrtf(x*x+y*y))-topradius)*h/(bottomradius-topradius);     if(phi>=0 && phi<w && r>=0 && r<h)     {         if(!interpolate || phi >= w-1 || r>=h-1)         {             //pick closest pixel             *p = data1[(int)r*w+(int)phi];         }         else         {             double dphi = modf(phi, &temp);             double dr = modf(r, &temp);              int8_t* c00 = (int8_t*)(data1+(int)r*w+(int)phi);             int8_t* c01 = (int8_t*)(data1+(int)r*w+(int)phi+1);             int8_t* c10 = (int8_t*)(data1+(int)r*w+w+(int)phi);             int8_t* c11 = (int8_t*)(data1+(int)r*w+w+(int)phi+1);              //interpolate components separately             for(int component = 0; component < 4; component++)             {                 double avg = ((*c00 & 0xff)*(1-dphi)+(*c01 & 0xff)*dphi)*(1-dr)+((*c10 & 0xff)*(1-dphi)+(*c11 & 0xff)*dphi)*dr;                 *p += (((int)(avg))<<(component*8));                 c00++; c10++; c01++; c11++;             }         }     } }  cgimageref result = cgbitmapcontextcreateimage(cgctx2);  // when finished, release context cgcontextrelease(cgctx1); cgcontextrelease(cgctx2); // free image data memory context if (data1) free(data1); if (data2) free(data2);  return result;  cgimagerelease(inimage); cgimagerelease(result); 

}

screenshot of errors

the leaks last 3 lines...

return result;  cgimagerelease(inimage); cgimagerelease(result); 

the 2 releases never called due return

you need this...

uiimage *image = [uiimage imagewithcgimage: result]; cgimagerelease(inimage);  cgimagerelease(result);  return image; 

update: have few more leaks well..

your call need this

cgimageref imageref = circularwrap3(timelapseimage.cgimage, 0, 1000, 0, yes, yes); uiimage *circularwrapimage = [uiimage imagewithcgimage:imageref]; cgimagerelease(imageref); 

and methods....

cgcontextref createargbbitmapcontext (size_t pixelswide, size_t pixelshigh) {     cgcontextref    context = null;     cgcolorspaceref colorspace;     void *          bitmapdata;     int             bitmapbytecount;     int             bitmapbytesperrow;      // declare number of bytes per row. each pixel in bitmap in     // example represented 4 bytes; 8 bits each of red, green, blue, ,     // alpha.     bitmapbytesperrow   = (int)(pixelswide * 4);     bitmapbytecount     = (int)(bitmapbytesperrow * pixelshigh);      // use generic rgb color space.     colorspace = cgcolorspacecreatedevicergb();      if (colorspace == null)     {         fprintf(stderr, "error allocating color space\n");         return null;     }      // allocate memory image data. destination in memory     // drawing bitmap context rendered.     bitmapdata = malloc( bitmapbytecount );     if (bitmapdata == null)     {         fprintf (stderr, "memory not allocated!");         cgcolorspacerelease( colorspace );         return null;     }      // create bitmap context. want pre-multiplied argb, 8-bits     // per component. regardless of source image format     // (cmyk, grayscale, , on) converted on format     // specified here cgbitmapcontextcreate.     context = cgbitmapcontextcreate (bitmapdata,                                      pixelswide,                                      pixelshigh,                                      8,      // bits per component                                      bitmapbytesperrow,                                      colorspace,                                      kcgimagealphapremultipliedfirst);     if (context == null)     {         free (bitmapdata);         fprintf (stderr, "context not created!");     }      // make sure , release colorspace before returning     cgcolorspacerelease( colorspace );      return context;      // not needed release contexts later on , wouldn't called anyway     //cgcontextrelease(context); }  cgimageref circularwrap3(cgimageref inimage,cgfloat bottomradius, cgfloat topradius, cgfloat startangle, bool clockwise, bool interpolate) {     //if(topradius < 0 || bottomradius < 0) return null;      // create bitmap context     int w = (int)cgimagegetwidth(inimage);     int h = (int)cgimagegetheight(inimage);      //result image side size (always square image)     int resultside = 2*max(topradius, bottomradius);     cgcontextref cgctx1 = createargbbitmapcontext(w,h);     cgcontextref cgctx2 = createargbbitmapcontext(resultside,resultside);      if (cgctx1 == null || cgctx2 == null)     {         //   *********************************************          //    leaking here if 1 of them not nulll         return null;     }      // image width, height. we'll use entire image.     cgrect rect = {{0,0},{w,h}};      // draw image bitmap context. once draw, memory     // allocated context rendering contain     // raw image data in specified color space.     cgcontextdrawimage(cgctx1, rect, inimage);      // can pointer image data associated bitmap     // context.     int *data1 = cgbitmapcontextgetdata (cgctx1);     int *data2 = cgbitmapcontextgetdata (cgctx2);      int resultimagesize = resultside*resultside;     double temp;     for(int *p = data2, pos = 0;pos<resultimagesize;p++,pos++)     {         *p = 0;         int x = pos%resultside-resultside/2;         int y = -pos/resultside+resultside/2;         cgfloat phi = modf(((atan2(x, y)+startangle)/2.0/m_pi+0.48),&temp);         if(!clockwise) phi = 1-phi;         phi*=w;         cgfloat r = ((sqrtf(x*x+y*y))-topradius)*h/(bottomradius-topradius);         if(phi>=0 && phi<w && r>=0 && r<h)         {             if(!interpolate || phi >= w-1 || r>=h-1)             {                 //pick closest pixel                 *p = data1[(int)r*w+(int)phi];             }             else             {                 double dphi = modf(phi, &temp);                 double dr = modf(r, &temp);                  int8_t* c00 = (int8_t*)(data1+(int)r*w+(int)phi);                 int8_t* c01 = (int8_t*)(data1+(int)r*w+(int)phi+1);                 int8_t* c10 = (int8_t*)(data1+(int)r*w+w+(int)phi);                 int8_t* c11 = (int8_t*)(data1+(int)r*w+w+(int)phi+1);                  //interpolate components separately                 for(int component = 0; component < 4; component++)                 {                     double avg = ((*c00 & 0xff)*(1-dphi)+(*c01 & 0xff)*dphi)*(1-dr)+((*c10 & 0xff)*(1-dphi)+(*c11 & 0xff)*dphi)*dr;                     *p += (((int)(avg))<<(component*8));                     c00++; c10++; c01++; c11++;                  }             }         }     }      cgimageref result = cgbitmapcontextcreateimage(cgctx2);      // when finished, release context     cgcontextrelease(cgctx1);     cgcontextrelease(cgctx2);     // free image data memory context     if (data1) free(data1);     if (data2) free(data2);      cgimagerelease(inimage);      return result; } 

Comments

Popular posts from this blog

android - Get AccessToken using signpost OAuth without opening a browser (Two legged Oauth) -

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: mockito -

google shop client API returns 400 bad request error while adding an item -