Reputation: 689
I have made an Intensity meter in a pictureBox. For making this intensity meter I have used a picture as Dialer(Dialer.bmp) and making needle using a line. I am doing this using openCV. And changing the needle pointer we have created a thread at form load. And the code is as follows
private: System::Void FocusExposure_Load(System::Object^ sender, System::EventArgs^ e) {
if(ExposureThreadStatus)
th->Abort();
th = gcnew Thread(gcnew ThreadStart(this,&FocusExposure::UpdateIntensity));
th->Start();
ExposureThreadStatus = true;
}
void UpdateIntensity()
{
Intensity_Values data;
while(1)
{
data = ReadImage(focusBuffer);
System::Drawing::Bitmap ^bmp=drawImageMeter(data.Max);
this->pictureBox1->Image =this->pictureBox1->Image->FromHbitmap(bmp->GetHbitmap());
delete bmp;
Sleep(1000);
}
}
System::Drawing::Bitmap^ drawImageMeter(float intensity_value)
{
IplImage *Background =cvLoadImage("Dialer.bmp", 1);
int width,height;
if(counter==1)
{
width=Background->width;
height=Background->height;
counter++;
needle_center.x=width/2;
needle_center.y=height/2;
needle_top.x=needle_center.x;
needle_top.y=needle_center.y-140;
}
double const PI = 3.14159265358979323;
int x1 = needle_top.x;
int y1 = needle_top.y;
int x0=needle_center.x;
int y0=needle_center.y;
float angle;
CurrIntensity = intensity_value;
angle = CurrIntensity-PreIntensity;
angle= 0.0703125f * angle;
// degrees, not radians
float radians = angle * (PI / 180.0f); // convert degrees to radians
if (current_max==1)
{
current_max++;
int N1x1 = needle_top.x;
int N1y1 = needle_top.y;
needle1_top.x = ((N1x1-x0) * cos(radians)) - ((N1y1-y0) * sin(radians)) + x0;
needle1_top.y = ((N1x1-x0) * sin(radians)) + ((N1y1-y0) * cos(radians)) + y0;
}
needle_top.x = ((x1-x0) * cos(radians)) - ((y1-y0) * sin(radians)) + x0;
needle_top.y = ((x1-x0) * sin(radians)) + ((y1-y0) * cos(radians)) + y0;
cvLine(Background, needle_center, needle1_top, CV_RGB(0, 0, 255), 1, 4, 0);
cvLine(Background, needle_center, needle_top, CV_RGB(255, 0, 0), 1, 4, 0);
System::Drawing::Bitmap ^bmp = gcnew System::Drawing::Bitmap(Background->width,Background->height,Background->widthStep,System::Drawing::Imaging::PixelFormat::Format24bppRgb,(System::IntPtr)Background->imageData);
PreIntensity = CurrIntensity;
return bmp;
}
This code is working fine and giving output as per my requirement. But The only problem is that when I am opening the form It is giving memory leak. I have seen in task manager and also used Intel Vtune profiler. This profiler is showing Mismatched allocation/deallocation at the following line
IplImage *Background =cvLoadImage("Dialer.bmp", 1);
We need to reload this image because we are drawing the line at the image and when needle pointer has changed it require the Dialer Image without needle.
Can anybody please suggest me any solution to solve this memory leak Issue.
Any help will be appreciated.
Upvotes: 1
Views: 1375
Reputation: 93410
It seems that drawImageMeter()
is being called more than once. The problem is that each time cvLoadImage()
is executed, it allocates space on the HEAP for the pixels. So after displaying the image you should release it with cvReleaseImage()
so the data get's freed.
A quick and dirty (and horrible) fix would be to make the variable
static:
static IplImage* Background =cvLoadImage("Dialer.bmp", 1);
But you should really change the design of your application so Background
it's allocated only once. To do that you can either make it global variable and load it on the main()
method, or make it a parameter of drawImageMeter()
:
System::Drawing::Bitmap^ drawImageMeter(IplImage* Background, float intensity_value)
{
// code
}
Upvotes: 3