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);
}
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
Post a Comment