I am trying to write a program in Visual C++ that will play a sound based on volume and frequency inputs gotten from pixels of a black and white video. To start, I am first trying to get a sound to play sans parameters (which I will add in later). I've already included winmm.lib into the project.
I've got code that compiles, but does not play a sound. The code I have so far is as follows:
sound.h (provided for me, works on another project):
//file: soundthread.h
#include <Windows.h> //new
#include <mmsystem.h>
#ifndef SOUNDTHREAD_H
#define SOUNDTHREAD_H
class Sound {
public:
static void init();
static void close(){waveOutReset(hWaveOut); waveOutClose(hWaveOut);};
static void writeAudioBlock(LPSTR block);
private:
static HWAVEOUT hWaveOut;
};
#endif
sound.cpp (provided for me, works on another project):
#include "stdafx.h"
#include "sound.h"
#include <mmsystem.h>
#include <mmreg.h>
HWAVEOUT Sound::hWaveOut;
void Sound::init(){
WAVEFORMATEX wfx;
wfx.nSamplesPerSec = 8000;
wfx.wBitsPerSample = 8;
wfx.nChannels = 1;
wfx.cbSize = 0;
wfx.wFormatTag = WAVE_FORMAT_PCM;
// wfx.nBlockAlign = (wfx.wBitsPerSample >> 2) * wfx.nChannels;
wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
/*
if(waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL)
!= MMSYSERR_NOERROR)
// int tt;
// tt = waveOutOpen(&hWaveOut, ((UINT)1), &wfx, 0, 0, CALLBACK_NULL);
// if(tt != MMSYSERR_NOERROR) {
fprintf(stderr, "unable to open WAVE_MAPPER device\n");
int tt;
tt = waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL);
MessageBox(0, "unable to open WAVE_MAPPER device\n", "Error", MB_ICONERROR|MB_OK);
/* DBG: tt=MMSYSERR_ALLOCATED;
tt=MMSYSERR_BADDEVICEID;
tt=MMSYSERR_NODRIVER;
tt=MMSYSERR_NOMEM;
tt=WAVERR_BADFORMAT; //** this is it //
tt=WAVERR_SYNC; // END DBG */
// ExitProcess(1);
// }
}
void Sound::writeAudioBlock(LPSTR block) {
WAVEHDR header;
ZeroMemory(&header, sizeof(WAVEHDR));
header.dwBufferLength = 500;
header.lpData = block;
waveOutPrepareHeader(hWaveOut, &header, sizeof(WAVEHDR));
waveOutWrite(hWaveOut, &header, sizeof(WAVEHDR));
do {
Sleep(100);
}while(waveOutUnprepareHeader(hWaveOut,&header,sizeof(WAVEHDR)) == WAVERR_STILLPLAYING);
}
soundplay.h (created by me for holding the provided OnSound() function):
#ifndef SOUNDPLAY_H //SOUNDPLAY_H_INCLUDED
#define SOUNDPLAY_H //SOUNDPLAY_H_INCLUDED
#include "sound.h"
void OnSound(); //update this w/ freq and intensity paramaters
#endif // SOUNDPLAY_H_INCLUDED
soundplay.cpp (created by me for holding the provided OnSound() function):
#include "stdafx.h"
#include <windows.h>
#pragma comment(lib, "winmm.lib")
#include <math.h> //used to be under sound.h
#include "sound.h"
#include <mmsystem.h>
#define PI 3.141592653f
#include "soundplay.h" //new
void OnSound()
{
// produce a sin wave sound.
float freq = 440.f;
DWORD Fs=8000;
int N=500;
float* tt=new float[N];
for(int i=0;i<N;i++)
{
tt[i]=(float)i/(float)Fs;
}
float intensity = 0.5f; //volume
float *signal=new float[N];
for(int i=0;i<N;i++)
{
signal[i]=intensity*sin(2.f*PI*freq*tt[i]);
}
BYTE* data=new BYTE[N];
for(int i=0;i<N;i++)
{
data[i]=(BYTE)(signal[i]+128.f);
}
delete []signal;
Sound::writeAudioBlock((LPSTR)data);
delete []data;
delete []tt;
}
Form1.h (code from the GUI designer containing the button that triggers OnSound to play a sound):
#include "sound.h" //new
#include "soundplay.h" //new
#pragma once
namespace a2c {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Summary for Form1
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::Button^ button1;
protected:
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->button1 = (gcnew System::Windows::Forms::Button());
this->SuspendLayout();
//
// button1
//
this->button1->Location = System::Drawing::Point(13, 225);
this->button1->Name = L"button1";
this->button1->Size = System::Drawing::Size(75, 23);
this->button1->TabIndex = 0;
this->button1->Text = L"Sound Test";
this->button1->UseVisualStyleBackColor = true;
this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(292, 273);
this->Controls->Add(this->button1);
this->Name = L"Form1";
this->Text = L"Form1";
this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
this->ResumeLayout(false);
}
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
//code for sound production
OnSound();
}
//NEW STUFF
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
Sound::init();
}
};
}
The contents of OnSound and sound.h and sound.cpp are from a sound example project that was created in Visual Studio 6.0 and modified for Visual Studio 2010 that works at playing the sound. My problem is that when I copy the code and try to use it in my own project, it compiles but doesn't play a sound when the button is pressed. Can anyone point me in the right direction?
Your problem is scaling the floating point samples into 8-bit unsigned data. Since intensity is 0.5, samples is going to be between -0.5 and 0.5. Adding 128 and truncating to a byte will give you data values of 128 or 127 - which is effectively zero. To scale to the full range of the BYTE you need to multiply by 127.
BYTE* data=new BYTE[N];
for(int i=0;i<N;i++)
{
data[i]=(BYTE)(signal[i]*127.f+128.f);
}
Additionally, unless you are okay with the quantization distortion, I would recommend adding some dither.
Michael Petch was right about the incomplete initialization of the sound system.
I added:
int tt;
tt = waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL);
to Sound::init() and it worked!
Thanks to all those who read and/or replied.
Related
I'm writing a thumbnail handler for a custom file type. When I register it, it returns with a success message. The "thumbnail" is shown as completely blank, but it does not say "no thumbnail available". The problem is, the actual thumbnail handler never gets called. I know this, because I put a series of statements in my handler under handler::initialize, handler::queryinterface and handler::getthumbnail. I have gone through most of this documentation., but all I can find is that I need to use initialize and getthumbnail. Here is my code:
Header:
#pragma once
#include <windows.h>
#include <thumbcache.h> // For IThumbnailProvider
#include <wincodec.h> // Windows Imaging Codecs
#include <fstream>
#include <iostream>
#pragma comment(lib, "windowscodecs.lib")
class ThumbnailProvider :
public IInitializeWithStream,
public IThumbnailProvider
{
public:
// IUnknown
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv);
IFACEMETHODIMP_(ULONG) AddRef();
IFACEMETHODIMP_(ULONG) Release();
// IInitializeWithStream
IFACEMETHODIMP Initialize(IStream *pStream, DWORD grfMode);
// IThumbnailProvider
IFACEMETHODIMP GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha);
ThumbnailProvider();
protected:
~ ThumbnailProvider();
private:
// Reference count of component.
long m_cRef;
// Provided during initialization.
IStream *m_pStream;
std::ofstream output;
void stripImageFrom (IStream *stream, HBITMAP *phbmp);
};
Body:
#include " ThumbnailProvider.h"
#include <Shlwapi.h>
#include <Wincrypt.h> // For CryptStringToBinary.
#include <msxml6.h>
#include <atlimage.h>
#include <fstream>
#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "Crypt32.lib")
#pragma comment(lib, "msxml6.lib")
extern HINSTANCE g_hInst;
extern long g_cDllRef;
ThumbnailProvider:: ThumbnailProvider() : m_cRef(1), m_pStream(NULL)
{
std::ofstream st;
st.open("C:\\Users\\labs\\Desktop\\Output\\out.txt", std::ios_base::app);
st << "Made provider";
st.close();
InterlockedIncrement(&g_cDllRef);
}
ThumbnailProvider::~ ThumbnailProvider()
{
InterlockedDecrement(&g_cDllRef);
}
#pragma region IUnknown
// Query to the interface the component supported.
IFACEMETHODIMP ThumbnailProvider::QueryInterface(REFIID riid, void **ppv)
{
std::ofstream st;
st.open("C:\\Users\\labs\\Desktop\\Output\\out.txt", std::ios_base::app);
st << "Querying interface";
st.close();
static const QITAB qit[] =
{
QITABENT( ThumbnailProvider, IThumbnailProvider),
QITABENT( ThumbnailProvider, IInitializeWithStream),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
}
// Increase the reference count for an interface on an object.
IFACEMETHODIMP_(ULONG) ThumbnailProvider::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
// Decrease the reference count for an interface on an object.
IFACEMETHODIMP_(ULONG) ThumbnailProvider::Release()
{
ULONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef)
{
delete this;
}
return cRef;
}
#pragma endregion
#pragma region IInitializeWithStream
// Initializes the thumbnail handler with a stream.
IFACEMETHODIMP ThumbnailProvider::Initialize(IStream *pStream, DWORD grfMode)
{
std::ofstream st;
st.open("C:\\Users\\labs\\Desktop\\Output\\out.txt", std::ios_base::app);
st << "Got to initialization";
st.close();
// A handler instance should be initialized only once in its lifetime.
HRESULT hr = HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
if (m_pStream == NULL)
{
// Take a reference to the stream if it has not been initialized yet.
hr = pStream->QueryInterface(&m_pStream);
}
return hr;
}
#pragma endregion
#pragma region IThumbnailProvider
// Gets a thumbnail image and alpha type. The GetThumbnail is called with the
// largest desired size of the image, in pixels. Although the parameter is
// called cx, this is used as the maximum size of both the x and y dimensions.
// If the retrieved thumbnail is not square, then the longer axis is limited
// by cx and the aspect ratio of the original image respected. On exit,
// GetThumbnail provides a handle to the retrieved image. It also provides a
// value that indicates the color at of the image and whether it has
// valid alpha in ation.
IFACEMETHODIMP ThumbnailProvider::GetThumbnail(UINT cx, HBITMAP *phbmp,
WTS_ALPHATYPE *pdwAlpha) {
std::ofstream st;
st.open("C:\\Users\\labs\\Desktop\\Output\\out.txt", std::ios_base::app);
st << "Getting thumbnail";
st.close();
ThumbnailProvider::stripImageFrom (m_pStream, phbmp);
cx = 1024 * 1024;
*pdwAlpha = WTSAT_UNKNOWN;
return S_OK;
}
#pragma endregion
#pragma region Helper Functions
// The PNG signature is 137 80 78 71 13 10 26 10. This does not make sense to do backward. I will do it forward.
void ThumbnailProvider::stripImageFrom (IStream *stream, HBITMAP *phbmp) {
unsigned long numBytes = 0;
unsigned long *numBytesPtr = &numBytes;
char *chptr = nullptr;
byte vals[8] = { 0 };
STATSTG *stat = nullptr;
DWORD temp = NULL;
stream->Stat(stat, temp);
unsigned long long length = stat->cbSize.QuadPart;
unsigned long long i;
for (i = 0; i<length; i++) {
stream->Read(chptr, 1, numBytesPtr);
if (*chptr == 137) {
vals[0] = 1;
}
else if (*chptr == 80 && vals[0]) {
vals[1] = 1;
}
else if (*chptr == 78 && vals[1]) {
vals[2] = 1;
}
else if (*chptr == 71 && vals[2]) {
vals[3] = 1;
}
else if (*chptr == 13 && vals[3]) {
vals[4] = 1;
}
else if (*chptr == 10 && vals[4] && !vals[5]) {
vals[5] = 1;
}
else if (*chptr == 26 && vals[5]) {
vals[6] = 1;
}
else if (*chptr == 10 && vals[6]) {
vals[7] = 1;
i -= 7;
break;
}
else {
memset(vals, 0, 8 * sizeof(vals[0]));
}
}
if (vals[7]) {
IStream *imgstream = nullptr;
stream->Read(imgstream, length-i, numBytesPtr);
CImage *img = nullptr;
img->Load(imgstream);
*phbmp = *img;
}
}
#pragma endregion
Everything else is just edited from one of Microsoft's examples, so I am pretty sure that is ok. The example is here.
If you're having this problem, make sure you're building for the right architecture. That solved it for me.
Currently I am working on the display of gray level image with zoom feature. I am able to get the position of the pixel and the zoom feature is working well. However I encountered two problems:
1.) How can I get the grey level value of the pixel that is pointed by the mouse? I only managed to obtain the rgb value through “QRgb rgbValue = pix.toImage().pixel(x,y)”. How can I convert it into grey level value? Or is there any direct way to get the grey level value of the pixel.
2.) I have implemented “mouseMoveEvent(QMouseEvent *event)” and “setMouseTracking(true)”. However the function of “mouseMoveEvent(QMouseEvent *event)” is not functioning when I move the mouse. What is wrong with my code?
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsItem>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
protected:
void mouseMoveEvent(QMouseEvent * event);
private:
Ui::MainWindow *ui;
QGraphicsScene* scene;
QGraphicsItem* item;
QPixmap pix;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QImage image("E:/image_00002.bmp");
pix = QPixmap::fromImage(image);
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
scene->addPixmap(pix);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
ui->graphicsView->setMouseTracking(true);
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
QPoint local_pt = ui->graphicsView->mapFromGlobal(event->globalPos());
QPointF img_coord_pt = ui->graphicsView->mapToScene(local_pt);
double x = img_coord_pt.x();
double y = img_coord_pt.y();
/* How can I get a gray level image here */
QRgb rgbValue = pix.toImage().pixel(x,y);
ui->label_X->setText(QString::number(x));
ui->label_Y->setText(QString::number(y));
ui->label_Value->setText(QString::number(rgbValue));
}
To elaborate a bit on what hank said. In order for your QMainWindow to receive the events from the QGraphicsScene you need to install an event filter (see http://qt-project.org/doc/qt-4.8/qobject.html#installEventFilter ). Quoting from the DOCs:
An event filter is an object that receives all events that are sent to this object.
The filter can either stop the event or forward it to this object.
In order to process the events you need to define an eventFilter method in your main window class. Below are the on_pushButton_clicked() and eventFilter() methods that should do what you want:
void MainWindow::on_pushButton_clicked()
{
ui->graphicsView->setMouseTracking(true);
scene->installEventFilter(this);
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::GraphicsSceneMouseMove ) {
QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent*>(event);
QPointF img_coord_pt = mouseEvent->scenePos();
double x = img_coord_pt.x();
double y = img_coord_pt.y();
QColor color = QColor(pix.toImage().pixel(x,y));
int average = (color.red()+color.green()+color.blue())/3;
ui->label_X->setText(QString::number(x));
ui->label_Y->setText(QString::number(y));
ui->label_Value->setText(QString::number(average));
return true;
} else {
return QObject::eventFilter(obj, event);
}
}
Does this help?
I've got the code (using VS2010, C++, Windows Forms Application) below:
#pragma once
#include <cv.h>
#include <highgui.h>
#ifdef _DEBUG
//debug
#pragma comment(lib,"cv210d.lib")
#pragma comment(lib,"cxcore210d.lib")
#pragma comment(lib,"cvaux210d.lib")
#pragma comment(lib,"highgui210d.lib")
#else
//release
#pragma comment(lib,"cv210.lib")
#pragma comment(lib,"cxcore210.lib")
#pragma comment(lib,"cvaux210.lib")
#pragma comment(lib,"highgui210.lib")
#endif
//Global variables
IplImage* src = NULL;
IplImage* hsv = NULL;
IplImage* dst = NULL;
IplImage* v_plane = NULL;
IplImage* h_plane = NULL;
IplImage* s_plane = NULL;
namespace HW4 {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Summary for Form1
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::PictureBox^ pictureBox1;
protected:
private: System::Windows::Forms::PictureBox^ pictureBox2;
private: System::Windows::Forms::Button^ ExitButton;
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->pictureBox1 = (gcnew System::Windows::Forms::PictureBox());
this->pictureBox2 = (gcnew System::Windows::Forms::PictureBox());
this->ExitButton = (gcnew System::Windows::Forms::Button());
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pictureBox1))->BeginInit();
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pictureBox2))->BeginInit();
this->SuspendLayout();
//
// pictureBox1
//
this->pictureBox1->Location = System::Drawing::Point(12, 49);
this->pictureBox1->Name = L"pictureBox1";
this->pictureBox1->Size = System::Drawing::Size(255, 212);
this->pictureBox1->SizeMode = System::Windows::Forms::PictureBoxSizeMode::StretchImage;
this->pictureBox1->TabIndex = 0;
this->pictureBox1->TabStop = false;
//
// pictureBox2
//
this->pictureBox2->Location = System::Drawing::Point(354, 49);
this->pictureBox2->Name = L"pictureBox2";
this->pictureBox2->Size = System::Drawing::Size(255, 212);
this->pictureBox2->SizeMode = System::Windows::Forms::PictureBoxSizeMode::StretchImage;
this->pictureBox2->TabIndex = 1;
this->pictureBox2->TabStop = false;
//
// ExitButton
//
this->ExitButton->Location = System::Drawing::Point(272, 278);
this->ExitButton->Name = L"ExitButton";
this->ExitButton->Size = System::Drawing::Size(64, 31);
this->ExitButton->TabIndex = 2;
this->ExitButton->Text = L"Exit";
this->ExitButton->UseVisualStyleBackColor = true;
this->ExitButton->Click += gcnew System::EventHandler(this, &Form1::ExitButton_Click);
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(635, 333);
this->Controls->Add(this->ExitButton);
this->Controls->Add(this->pictureBox2);
this->Controls->Add(this->pictureBox1);
this->Name = L"Form1";
this->Text = L"Form1";
this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pictureBox1))->EndInit();
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pictureBox2))->EndInit();
this->ResumeLayout(false);
}
#pragma endregion
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
src = cvLoadImage("D:\\Pictures\\hungry.jpg");
dst = cvCreateImage(cvGetSize(src),8,3);
hsv = cvCreateImage(cvGetSize(src),8,3);
h_plane = cvCreateImage(cvGetSize(src),8,1);
s_plane = cvCreateImage(cvGetSize(src),8,1);
v_plane = cvCreateImage(cvGetSize(src),8,1);
cvCvtColor(src,hsv,CV_BGR2HSV);
cvSplit(hsv,h_plane,s_plane,v_plane,0);
cvEqualizeHist(v_plane,v_plane);
cvMerge(h_plane,s_plane,v_plane,0,hsv);
cvCvtColor(hsv,dst,CV_HSV2BGR);
//Before you debug, choose SizeMode property of PictureBoxs = StretchImage.
pictureBox1->Image = gcnew //replacement of cvShowImage
System::Drawing::Bitmap(src->width,src->height,src->widthStep,
System::Drawing::Imaging::PixelFormat::Format24bppRgb,(System::IntPtr) src->imageData);
pictureBox1->Refresh();
pictureBox2->Image = gcnew //replacement of cvShowImage
System::Drawing::Bitmap(dst->width,dst->height,dst->widthStep,
System::Drawing::Imaging::PixelFormat::Format24bppRgb,(System::IntPtr) dst->imageData);
pictureBox2->Refresh();
/*cvReleaseImage(&src);
cvReleaseImage(&hsv);
cvReleaseImage(&dst);
cvReleaseImage(&h_plane);
cvReleaseImage(&s_plane);
cvReleaseImage(&v_plane);*/
}
private: System::Void ExitButton_Click(System::Object^ sender, System::EventArgs^ e) {
cvReleaseImage(&src);
cvReleaseImage(&hsv);
cvReleaseImage(&dst);
cvReleaseImage(&h_plane);
cvReleaseImage(&s_plane);
cvReleaseImage(&v_plane);
this->Close();
}
};
}
Consider the part of code:
cvReleaseImage(&src);
cvReleaseImage(&hsv);
cvReleaseImage(&dst);
cvReleaseImage(&h_plane);
cvReleaseImage(&s_plane);
cvReleaseImage(&v_plane);
if i put this part at the end of the Form1_Load, there'll be an error as the following picture:
However, if i put this part in the ExitButton_Click function, it's ok!
i don't know why ? hope someone can give me an explaination ! thanks for your help !^~^
In the following line you are using opencv image buffers and if you fee these buffers in the end of form load function, .net engine could not load image anymore
But if you free the buffer in form exit, it won't care ...
pictureBox1->Image = gcnew ...
The Form-Load event in .Net can be used to allocate resources before the form is loaded and rendered. By freeing the image buffer at the end of the load, you remove the image resource that the form needs to display. Just imagine that there is some internal method that calls your Load() method and then it calls an internal Display() method, which uses data from the Load() method. If you load the data and then release it before the "Display()" method is called, you are freeing memory that is required in the Display() method.
As Roozbeh said, if you put it in the exit, the form is not trying to display anything so it doesn't need that image resource (from the buffer). The exit method is naturally a good place to deallocate things.
I'm a C++-CLI beginner and I have to get familiar with some simple things.
I made a form with 1 label and 1 button.
I want to change the text of the label by clicking on the button and calling some text via a void in another cpp class (changetext.cpp)
Structure:
Form1.h //just a regular form code with 1 label and 1 button handler at the end
#pragma once
namespace ms {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Summary for Form1
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
public:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
public: System::Windows::Forms::Label^ label1;
private: System::Windows::Forms::Button^ button1;
public:
public:
public:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->label1 = (gcnew System::Windows::Forms::Label());
this->button1 = (gcnew System::Windows::Forms::Button());
this->SuspendLayout();
//
// label1
//
this->label1->AutoSize = true;
this->label1->Location = System::Drawing::Point(313, 140);
this->label1->Name = L"label1";
this->label1->Size = System::Drawing::Size(35, 13);
this->label1->TabIndex = 0;
this->label1->Text = L"label1";
//
// button1
//
this->button1->Location = System::Drawing::Point(101, 117);
this->button1->Name = L"button1";
this->button1->Size = System::Drawing::Size(100, 58);
this->button1->TabIndex = 1;
this->button1->Text = L"button1";
this->button1->UseVisualStyleBackColor = true;
this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(467, 262);
this->Controls->Add(this->button1);
this->Controls->Add(this->label1);
this->Name = L"Form1";
this->Text = L"Form1";
this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
public: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
}
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
changetext my = new changetext();
my.changeText();
}
};
}
ms.cpp (main) //just creates the form
// ms.cpp : main project file.
#include "stdafx.h"
#include "Form1.h"
using namespace ms;
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
// Enabling Windows XP visual effects before any controls are created
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
// Create the main window and run it
Application::Run(gcnew Form1());
return 0;
}
changetext.cpp
#include "stdafx.h"
#include "Form1.h"
int number;
void changeText()
{
number = 5;
Form1.label1->Text=number;
}
I am making a little mistake somewhere and I guess it has to do with header files, I'm used to code in java so headerfiles are not my cup of tea yet.
This is what to do:
Create getter in changetext.cpp
#include "stdafx.h"
#include "Form1.h"
int number = 5;
void getNumber()
{
return number;
}
Create header.h
#pragma once
void getNumber();
Include header.h and edit Form1.h
#pragma once
#include header.h
namespace ms {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Summary for Form1
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
public:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
public: System::Windows::Forms::Label^ label1;
private: System::Windows::Forms::Button^ button1;
public:
public:
public:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->label1 = (gcnew System::Windows::Forms::Label());
this->button1 = (gcnew System::Windows::Forms::Button());
this->SuspendLayout();
//
// label1
//
this->label1->AutoSize = true;
this->label1->Location = System::Drawing::Point(313, 140);
this->label1->Name = L"label1";
this->label1->Size = System::Drawing::Size(35, 13);
this->label1->TabIndex = 0;
this->label1->Text = L"label1";
//
// button1
//
this->button1->Location = System::Drawing::Point(101, 117);
this->button1->Name = L"button1";
this->button1->Size = System::Drawing::Size(100, 58);
this->button1->TabIndex = 1;
this->button1->Text = L"button1";
this->button1->UseVisualStyleBackColor = true;
this->button1->Click += gcnew System::EventHandler(this,&Form1::button1_Click);
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(467, 262);
this->Controls->Add(this->button1);
this->Controls->Add(this->label1);
this->Name = L"Form1";
this->Text = L"Form1";
this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
public: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
}
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
label1->Text=""+getNumber();
}
};
}
I have two file generated in visual studio c++ 2010 express.
test2.cpp
// test2.cpp : main project file.
#include "stdafx.h"
#include "Form1.h"
using namespace test2;
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
// Enabling Windows XP visual effects before any controls are created
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
// Create the main window and run it
Application::Run(gcnew Form1());
return 0;
}
and Form1.h
#pragma once
namespace test2 {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Summary for Form1
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::WebBrowser^ webBrowser1;
public: System::Windows::Forms::Timer^ timer1;
private:
private: System::ComponentModel::IContainer^ components;
protected:
private:
/// <summary>
/// Required designer variable.
/// </summary>
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->components = (gcnew System::ComponentModel::Container());
this->webBrowser1 = (gcnew System::Windows::Forms::WebBrowser());
this->timer1 = (gcnew System::Windows::Forms::Timer(this->components));
this->SuspendLayout();
//
// webBrowser1
//
this->webBrowser1->Dock = System::Windows::Forms::DockStyle::Fill;
this->webBrowser1->IsWebBrowserContextMenuEnabled = false;
this->webBrowser1->Location = System::Drawing::Point(0, 0);
this->webBrowser1->MinimumSize = System::Drawing::Size(20, 20);
this->webBrowser1->Name = L"webBrowser1";
this->webBrowser1->ScrollBarsEnabled = false;
this->webBrowser1->Size = System::Drawing::Size(284, 262);
this->webBrowser1->TabIndex = 0;
this->webBrowser1->Url = (gcnew System::Uri(L"http://wp.pl", System::UriKind::Absolute));
this->webBrowser1->DocumentCompleted += gcnew System::Windows::Forms::WebBrowserDocumentCompletedEventHandler(this, &Form1::webBrowser1_DocumentCompleted);
//
// timer1
//
this->timer1->Enabled = true;
this->timer1->Interval = 10000;
this->timer1->Tick += gcnew System::EventHandler(this, &Form1::timer1_Tick);
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(284, 262);
this->Controls->Add(this->webBrowser1);
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
this->Name = L"Form1";
this->ResumeLayout(false);
}
#pragma endregion
private: System::Void webBrowser1_DocumentCompleted(System::Object^ sender, System::Windows::Forms::WebBrowserDocumentCompletedEventArgs^ e) {
}
public: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e) {
Application::Exit();
}
};
}
How to using argument from command prompt? For example how change
this->timer1->Interval = 10000;
on user var? Something like
this->timer1->Interval = time;
You can get a string array containing the command-line arguments by calling Environment::GetCommandLineArgs.