An easy C++ program

Access to COM servers using C++ can be as easy as with scripts as you can see if you compare the program in this topic with the version in the previous topic - both performing the same task (for details, see the previous topic). The easy approach presented here is possible by exploiting the informations in the type library which is stored in BrainVoyager.exe. The informations in the type library are accessed with the "#import" statement in one of the first lines of the program. The #import-technique also provides "smart pointers" to interfaces. With these smart pointers, you do not have to care about calling "Release" to release a reference of a particular interface when you no longer need the reference. This and other "bookkeeping" operations are done automatically with smart pointers. To use a smart pointer, append "Ptr" after the interface name, i.e. IApplicationPtr is used below to access the IApplication interface.
Note, however, that the type library technique presented here works only with the Microsoft Visual C++ compiler. If you use another compiler, you must use the general approach as described in the previous topic.


// BrainVoyagerEasyClient.cpp
// Adjust the following path if your BV is not in "C:\Program Files\BrainVoyager"
#import "C:\Program Files\BrainVoyager\BrainVoyager.exe" no_namespace
#include <fstream.h>
BOOL MyLoadVMR(const char *filename);
BOOL MySaveVMR(const char *filename);
BYTE *Vol;  // Pointer to VMR data set
int DimX, DimY, DimZ;
void main()
{
	CoInitialize(NULL);
	// direct access to IApplication interface
	IApplicationPtr BVApplication(__uuidof(BrainVoyager));
	char path[_MAX_PATH], filename[_MAX_PATH];
	// Adjust the following path if necessary
	strcpy(path, "D:\\Program Files\\Samples\\ObjectsRawData\\");
	strcpy(filename, path);
	strcat(filename, "cg2_tal.vmr");
	// Easy and direct access to IDocument interface
	// OpenDocument works like in scripts: it returns the Document object
	IDocumentPtr BVDoc = BVApplication->OpenDocument(filename);
	// Call document methods
	//BVDoc->SetZoomLevel(2);
	BVDoc->Hide3DVolumeTools();
	// Now let's work on a BrainVoyager file format: a VMR file
	int new_val;
	if(MyLoadVMR(filename))
	{
		int x, y, z;
		for(x=0; x<DimX; x++)
		{
			for(y=0; y<DimY; y++)
			{
				for(z=0; z<DimZ; z++)
				{
					new_val = Vol[z*DimY*DimX + y*DimX + x];
					if((new_val > 30) && (new_val < 226))  // > 10
						new_val = 225 - new_val + 10;
					Vol[z*DimY*DimX + y*DimX + x] = (BYTE)max(0, new_val);
				}
			}
		}
		strcpy(filename, path);
		strcat(filename, "cg2_tal_inv.vmr");
		MySaveVMR(filename);
		free(Vol);
		IDocumentPtr BVDoc = BVApplication->OpenDocument(filename);
		//BVDoc->SetZoomLevel(2);
		BVDoc->Hide3DVolumeTools();
	}
	
	BVDoc = NULL;
	BVApplication = NULL;
	CoUninitialize();
}
BOOL MyLoadVMR(const char *filename)
{
	ifstream VMRFile( filename, ios::binary | ios::nocreate );
	if( !VMRFile ) 
	{
		cout << "ERROR: Cannot open VMR file." << endl;
		return FALSE;
	}
	unsigned short Nx, Ny, Nz;
	
	VMRFile.read((char *)(&Nx), sizeof(unsigned short));
	VMRFile.read((char *)(&Ny), sizeof(unsigned short));
	VMRFile.read((char *)(&Nz), sizeof(unsigned short));
	DimX = (int)Nx;
	DimY = (int)Ny;
	DimZ = (int)Nz;
	cout << Nx << " " << Ny << " " << Nz << endl;
	if((Vol = (BYTE *)malloc(Nz*Ny*Nx*sizeof(BYTE))) == NULL)
	{
		cout << "ERROR: Cannot allocate memory for VMR file." << endl;
		return FALSE;
	}
	VMRFile.read(Vol, Nx*Ny*Nz*sizeof(BYTE));
	return TRUE;
}
BOOL MySaveVMR(const char *filename)
{
	ofstream VMRFile( filename, ios::binary | ios::trunc );
	if( !VMRFile ) 
	{
		cout << "ERROR: Cannot open VMR file." << endl;
		return FALSE;
	}
	unsigned short Nx, Ny, Nz;
	Nx = (unsigned short)DimX;
	Ny = (unsigned short)DimY;
	Nz = (unsigned short)DimZ;
	cout << Nx << " " << Ny << " " << Nz << endl;
	
	VMRFile.write((char *)(&Nx), sizeof(unsigned short));
	VMRFile.write((char *)(&Ny), sizeof(unsigned short));
	VMRFile.write((char *)(&Nz), sizeof(unsigned short));
	VMRFile.write(Vol, Nx*Ny*Nz*sizeof(BYTE));
	return TRUE;
}