Skip to main content
GameDev.net gamedev.net
🔒 Locked

Plotting(to file) libraries

Started by Dwiel Nov 25, 2003 at 7:30 PM 5 replies 350+ views
Original Post
Dwiel
Dwiel
Hello, I have spent quite a while trying to figure out how to do what I want to do which is run some basic plotting to file from within my C++ code. I looked at using gnuplot and giving it batch files but saving the plots to file actually got complicated and the annoying full screen popup window was a pain (I am using windows here). It would be really nice if someone knows of a way I could say pass an object a pointer to a vector of floats for my x data and the same for my y... something that simple will suffice for now. It would be nice if it had some more complex things but I''m pretty desperate right now... Thanks! Dwiel
SpaceDude
SpaceDude
You want to save it in same kind of graphics format? .bmp file or something?

If you look up the file specification for the .bmp format, it shouldn''t be too hard to start with all pixels white and then change the pixels at your x and y positions to black. Clearly you gonna have to do some extra work to draw your x and y axis with labels and then scale your data points to fit to the size of the picture... But if you do it like that you''ll have full control over what is drawn if you want to add some more complicated stuff later...

Probably not what you wanted but anyway...
Dwiel
Dwiel
Yeah... I did think of that... I just figured that someone else has already done it so why should I? Other than for the learning experience... If I want to do this for experience later I can... right now, I am doing something else...

Thanks for the suggestion though...

Anyone else?

Surely someone has writen their own sooner or later...

Dwiel
grhodes_at_work
grhodes_at_work
If you have the financial means, then you will want to look at Tecplot Edge from AMTEC. Its the ultimate graphic tool. And I do mean ultimate. See my comments on Tecplot below.

DPLOT is a pretty nice shareware (or, with less features, freeware) graphing program that may do what you want. Its been around for a decade (despite the limited history shown on the web site below), but the author David Hyde has continuously refined it. It has a lot of nice options. The only discouraging thing is that after all these years it still seems to not provide a nice API that allows you to embed graphs within your own window. It always pops up as a full separate application with menu and all. To call it from your app you either have to create a data file (quite simple formatting) and just launch the app to view the graph or, (HORRORS, SHUTTERING), communicate to the app via the totally ancient DDE protocol.

www.dplot.com

The freeware version may suit your needs.

My absolutely, all-time favorite plotting/visualization package---which you should consider if you have the financial means, is Tecplot, from AMTEC. See link below. The file format for Tecplot is quite simple. The Tecplot Edge version is an API that allows you to integrate Tecplot graphics into your own app. It seems that you cannot embed a Tecplot window as a child of your own---you'll see a popup---but you can hide all the normal Tecplot menus and add your own dialog controls, etc. HIGHLY, massively recommended if you do heavy plotting---2D and/or 3D---and need the very ultimate in customization and configurability. Absolutely beautiful/perfect hard copy output as well.

www.amtec.com

I don't know what the current pricing is. The last time I checked (version 7.5), full Tecplot was around $1500, or $500 for a full featured academic version. I think there may have been a light, feature-limited academic version for less. I have no idea about Tecplot Edge.

Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.

[edited by - grhodes_at_work on November 26, 2003 10:20:07 AM]
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
Ready4Dis
Ready4Dis
You could probably use my bitmap loading/writing class to do what you need...

Bitmap.h

#ifndef Bitmap_H
#define Bitmap_H

#include <stdio.h>

#pragma pack(1) //Don''t pack our structs!!!


/***** Some Structures for our bitmap class! *****/
struct BmpHeader_S
{
//Standard Header

unsigned char Signature[2]; //Should always be BM

unsigned long FileSize; //Size of complete file!

unsigned long Reserved; //4 reserved bytes...

unsigned long DataOffset; //Start of data in file!


//Info Header

unsigned long InfoHeader_Size; //should=40

unsigned long Width; //Width of our bitmap!

unsigned long Height; //Height of our bitmap!

unsigned short Planes; //Number of planes.. =1

unsigned short BitCount; //How many bits per pixel

unsigned long Compression; //0 = none, 1=8-bit, 2=4-bit

unsigned long ImageSize; //size of image, can set to 0 if compression = 0!


unsigned long XPixelsPerM; //horizontal pixels per meter!

unsigned long YPixelsPerM; //vertical pixels per meter!


unsigned long ColorsUsed; //Number of actual colors used!

unsigned long ColorsImportant; //Colors that are important.. 0 = all

};

struct Pallete_S
{
unsigned char ColorsLoaded; //How large is our pallete?

unsigned char ColorsUsed; //How many colors are in the pallete currently

unsigned char *Pal; //Pointer to our pallete... ColorsLoaded*3 (r,g,b)

};

/***** Our bitmap class *****/
class Bitmap_C
{
public:
BmpHeader_S OriginalHeader; //Our original bitmaps header!

Pallete_S OriginalPal; //Original pallete

BmpHeader_S CurrentHeader; //Our current header!

unsigned long Size24Bit; //width*height*3!!!

unsigned char *Data; //Our data in memory


public:
//Our Constructors...

Bitmap_C(void);
Bitmap_C(unsigned long W, unsigned long H, unsigned char BD);
Bitmap_C(char *fName);

//Release any data we have allocated!

void Close(void);
//Load a bitmap from file!

char Load(char *fName);
//Create a blank bitmap with these dimensions to write to!

char Create(unsigned long W, unsigned long H, unsigned char BD);
//Save our bitmap!

char Save(char *fName, unsigned short BitDepth);

//Our destructor

~Bitmap_C(void);

//Our private functions!!

private:

void Load_24(FILE *in);
char Load_8(FILE *in);

void Save_24(FILE *out);

void Save_8(FILE *out);
void Create_Pallete(void); //Used by Save_8 to create pal


void Create_Current(void);
};

#endif


Bitmap.cpp

// Bitmap.cpp

//

// Implimentation of a generic bitmap loading/saving/management class.

// Written by Bill Bryan - July 2002


#include "Bitmap.h"
#include <memory.h>
#include <conio.h>

/**/
/*
Bitmap_C::Load_24() Bitmap_C::Load_24()

NAME
Bitmap_C::Load_24() - loads a 24-bit bitmap file

SYNOPSIS
void Bitmap_C::Load_24(FILE *in)
FILE *in File pointer for input

DESCRIPTION
Reads a 24 bit bitmap from the disk, saves it in memory with a full header.

SEE ALSO

RETURNS

NOTE
Private function.
*/

/**/
void Bitmap_C::Load_24(FILE *in)
{
long x,y;
unsigned long offset;

// scan every row in the file

// rows are scanned in reverse order because they are stored upside-down

// in a bitmap file.

for (y=OriginalHeader.Height-1;y!=-1;--y)
{
// move to the start of the row

offset=y*OriginalHeader.Width*3;
for (x=0;x!=OriginalHeader.Width;++x)
{
Data[offset+2]=getc(in); // Read Blue

Data[offset+1]=getc(in); // Read Green

Data[offset]=getc(in); // Read Red


offset+=3; // Move to next pixel

}
}
}

/**/
/*
Bitmap_C::Load_8() Bitmap_C::Load_8()

NAME
Bitmap_C::Load_8() - loads a 8-bit bitmap file

SYNOPSIS
char Bitmap_C::Load_8(FILE *in)
FILE *in File pointer for input

DESCRIPTION
Reads an 8 bit bitmap from the disk, saves it in memory with a full header.

SEE ALSO

RETURNS
0 No error
3 Out of memory

NOTE
Private function.
*/

/**/
char Bitmap_C::Load_8(FILE *in)
{
long x,y;
unsigned long offset, offset2=0;
unsigned short Index;
OriginalPal.Pal = new unsigned char[256*3]; // allocate our pallete

OriginalPal.ColorsLoaded = 255; // note that we are using a pallette

if (!OriginalPal.Pal) // If we could not allocate that memory...

return 3; // Exit funciton, return error code.


// Load Pallette into memory.

for (offset=0;offset!=256;++offset)
{
OriginalPal.Pal[offset2+2]=getc(in); // Read Blue

OriginalPal.Pal[offset2+1]=getc(in); // Read Green

OriginalPal.Pal[offset2]=getc(in); // Read Red

getc(in); // Intensity, but don''t need it.

offset2+=3; // move to next pallette entry.

}

// Load image data. Because we are storing these images as 24-bit in memory,

// The information is read in and converted to RGB components from the pallete index.


// scan every row.

for (y=OriginalHeader.Height-1;y!=-1;--y)
{
// Move to beginning of row, scan every pixel

offset=y*OriginalHeader.Width*3;
for (x=0;x!=OriginalHeader.Width;++x)
{
Index = getc(in); // Read Pallete entry

Index*=3; // Adjust to read from our pallette table

Data[offset] = OriginalPal.Pal[Index]; // Copy Red

Data[offset++] = OriginalPal.Pal[Index+1]; // Copy Green

Data[offset++] = OriginalPal.Pal[Index+2]; // Copy Blue


offset+=3; // Move to next pixel.

}
}
// Return a successful read.

return 0;
}

/**/
/*
Bitmap_C::Create_Current() Bitmap_C::Create_Current()

NAME
Bitmap_C::Create_Current() - Creates a header for the image in memory

SYNOPSIS
void Bitmap_C::Create_Current(void)

DESCRIPTION
Creates a header for the image in memory based on the original header
and currend image data

SEE ALSO

RETURNS

NOTE
Private function.
*/

/**/
void Bitmap_C::Create_Current(void)
{
unsigned long tSize;

// First copy our original header to the current via a direct memory copy.

memcpy(&CurrentHeader,&OriginalHeader,sizeof(BmpHeader_S));

// Figure out the final file size (header + image data)

tSize = CurrentHeader.Width*CurrentHeader.Height*3;

// Now set all our variables up for our current that *could* differ

CurrentHeader.FileSize=sizeof(BmpHeader_S)+tSize; // Output file size

CurrentHeader.BitCount=24; // 24-bit image

CurrentHeader.DataOffset=54; // Start of data

CurrentHeader.InfoHeader_Size=40; // Standard 40byte info header

CurrentHeader.ImageSize=0; // Image Size =0 (forces autocalculation)

CurrentHeader.Planes=1; // Only one plane

}


/**/
/*
Bitmap_C::Load() Bitmap_C::Load()

NAME
Bitmap_C::Load() - loads a 24-bit bitmap file

SYNOPSIS
char Bitmap_C::Load(unsigned char *fName)
unsigned char *fName the name of the file being loaded

DESCRIPTION
Opens the file the user asks for, determines if it''s valid, and what bit-depth.
It then attempts to load that file into memory.

SEE ALSO

RETURNS
0 No Error
1 Could Not Open File
2 Invalid File Format
3 Insufficient Memory

NOTE
*/

/**/
char Bitmap_C::Load(char *fName)
{
FILE *in;
unsigned char Ret;

Close();

in = fopen(fName,"rb");
if (!in) // If the file didn''t open...

return 1; // ... report error to user.


// Read the header into memory as a continuous stream of bytes.

fread(&OriginalHeader,1,sizeof(BmpHeader_S),in);

//Check for a valid bitmap!

if (OriginalHeader.Signature[0]!=''B'' ||OriginalHeader.Signature[1]!=''M'')
{ // An invalid file

fclose(in); // close our file!

return 2; // report invalid file format error

}

// With the valid bitmap, calculate the size needed to store.

Size24Bit = OriginalHeader.Width*OriginalHeader.Height*3;

// Allocate some memory for our image.

Data = new unsigned char[Size24Bit];

if (!Data) // If memory allocation fails...

{
fclose(in); // Close the file

return 3; // repot not enough memory error

}

fseek(in,OriginalHeader.DataOffset,0); //Seek to the image data


if (OriginalHeader.BitCount==8) // If it''s a pallette based image

{
Ret=Load_8(in); // Load 8-bit, get return value

if (Ret==3) // if the memory can''t be allocated

{
delete Data; // Delete our 24-bit image space

Data=0; // Mark it as deleted

fclose(in); // Close our file

return 3; // return Not enough memory error

}
}
else if (OriginalHeader.BitCount==24) // If it''s a true color image

{
Load_24(in); // Load 24-bit

}

fclose(in); // Close the file


Create_Current(); // Creates our current header from our original


return 0; // return no errors.

}


/**/
/*
Bitmap_C::Save_24() Bitmap_C::Save_24()

NAME
Bitmap_C::Save_24() - saves a 24-bit image file

SYNOPSIS
void Bitmap_C::Save_24(FILE *out)
FILE *out File pointer for output

DESCRIPTION
Saves the 24-bit image in memory to the disk.

SEE ALSO

RETURNS

NOTE
Private function.
*/

/**/
void Bitmap_C::Save_24(FILE *out)
{
long x,y;
unsigned long off;

// write the current header to the disk directly

fwrite(&CurrentHeader,1,sizeof(BmpHeader_S),out);

// scan along the rows from bottom-up

for (y=CurrentHeader.Height-1;y!=-1;--y)
{
// move to start of row, go pixel by pixel

off = y*CurrentHeader.Width*3;
for (x=0;x!=CurrentHeader.Width;++x)
{
putc(Data[off+2],out); // Write blue

putc(Data[off+1],out); // Write Green

putc(Data[off],out); // Write Red


off+=3;
}
}
}


/**/
/*
Bitmap_C::Save_8() Bitmap_C::Save_8()

NAME
Bitmap_C::Save_8() - saves an 8-bit image

SYNOPSIS
void Bitmap_C::Save_8(FILE *out)
FILE *out File pointer for output

DESCRIPTION
Writes the image in memory to disk as a palletized image.

SEE ALSO

RETURNS

NOTE
Private function. Not currently implimented. Saves as 24-bit.
This is a stand in function.
*/

/* NOT CURRENTLY IMPLEMENTED, SAVES AS 24-BIT BITMAP FOR NOW */
void Bitmap_C::Save_8(FILE *out)
{
long x,y;
unsigned long off;
fwrite(&CurrentHeader,1,sizeof(BmpHeader_S),out);
for (y=CurrentHeader.Height-1;y!=-1;--y)
{
off = y*CurrentHeader.Width*3;
for (x=0;x!=CurrentHeader.Width;++x)
{
putc(Data[off+2],out);
putc(Data[off+1],out);
putc(Data[off],out);

off+=3;
}
}
}

/**/
/*
Bitmap_C::Save() Bitmap_C::Save()

NAME
Bitmap_C::Save() - Allows user to save the image

SYNOPSIS
char Bitmap_C::Save(char *fName, unsigned short BitDepth=0);
char *fName Name of output file.
unsigned short BitDepth Desired bit-depth of output image

DESCRIPTION
User calls this function to output an image from memory to the disk.

SEE ALSO

RETURNS
0 No Errors
1 Could Not Open File
2 Invalid File Format / Invalid bit depth

NOTE
*/

/**/
char Bitmap_C::Save(char *fName, unsigned short BitDepth=0)
{
FILE *out;
out = fopen(fName,"wb");
if (!out) // If we could not open the output file

return 1; // return could not open file error


if (BitDepth==0) // If the bit depth isn''t set...

BitDepth=OriginalHeader.BitCount; // Default to the original bit depth


switch (BitDepth)
{
case 8: // For an 8-bit image

Save_8(out); // use the 8-bit saving function

break;
case 24:
Save_24(out); // For a 24-bit image

break; // use the 24-bit saving function

default:
{
fclose(out); // close the file

return 2; // return Invalid file format/bitdepth error

}
}

fclose(out); // Close the file.

return 0; // Return Success code.

}

/**/
/*
Bitmap_C::Create() Bitmap_C::Create()

NAME
Bitmap_C::Create() - creates a new blank image in memory

SYNOPSIS
char Bitmap_C::Create(unsigned long W, unsigned long H, unsigned char BD)
unsigned long W desired width
unsigned long H desired height
unsigned long BD desired bit-depth (color)

DESCRIPTION
Creates a new blank image in memory of width W, height H, and with a
color bit depth of BD.

SEE ALSO

RETURNS

NOTE
The image is always stored in memory as a 24-bit true color image.
BD is a file saving default that the user can set.
*/

/**/
char Bitmap_C::Create(unsigned long W, unsigned long H, unsigned char BD)
{
unsigned long tSize;
Close(); // Close up any loose ends there may be.


memset(&OriginalHeader,0,sizeof(BmpHeader_S)); // Clear the memory that holds the header

OriginalHeader.Signature[0]=''B''; // Put in file ID tag

OriginalHeader.Signature[1]=''M''; // Put in file ID tag

OriginalHeader.BitCount=BD; // Set bit depth

OriginalHeader.Width = W; // Set Width

OriginalHeader.Height = H; // Set height


OriginalHeader.Planes = 1; // Set # of planes

OriginalHeader.InfoHeader_Size=40; // set header size (always 40)

OriginalHeader.DataOffset = 54; // Start of image data = 54


tSize = W*H*3; // Find out and save file size

OriginalHeader.FileSize = sizeof(BmpHeader_S)+tSize;

Data = new unsigned char[tSize]; // Allocate image in memory

memset(Data,0,tSize); // clear it all to black.


Create_Current(); // Create the current working header


return 0; //No errors!

}

/**/
/*
Bitmap_C::Close() Bitmap_C::Close()

NAME
Bitmap_C::Close() - clears out memory

SYNOPSIS
void Bitmap_C::Close(void)

DESCRIPTION
Deletes any dynamically allocated memory that the class has. This
is to make sure there are no abandoned memory chunks when a new image
gets loaded or created.

SEE ALSO

RETURNS

NOTE
*/

/**/
void Bitmap_C::Close(void)
{
if (OriginalPal.Pal) // If there''s a pallette

{
delete OriginalPal.Pal; // delete pallete

OriginalPal.Pal = 0; // mark as deleted

}

if (Data) // If there''s image data

{
delete Data; // delete image data

Data=0; // mark as deleted

}

memset(&OriginalHeader,0,sizeof(BmpHeader_S)); // Clear out the header

OriginalPal.ColorsLoaded=0; // Set colors loaded to 0 in pallette

}

/**/
/*
Bitmap_C::Bitmap_C() Bitmap_C::Bitmap_C()

NAME
Bitmap_C::Bitmap_C() - Constructor

SYNOPSIS
Bitmap_C::Bitmap_C(void)

DESCRIPTION
Creates a new bitmap object with no attributes at all.

SEE ALSO

RETURNS

NOTE
*/

/**/
Bitmap_C::Bitmap_C(void)
{
Data=0;
OriginalPal.Pal=0;
OriginalPal.ColorsLoaded=0;
memset(&OriginalHeader,0,sizeof(BmpHeader_S));
}

/**/
/*
Bitmap_C::Bitmap_C() Bitmap_C::Bitmap_C()

NAME
Bitmap_C::Bitmap_C() - Constructor

SYNOPSIS
Bitmap_C::Bitmap_C(char *fName)
char *fName File to be loaded into memory.

DESCRIPTION
Creates a new bitmap object and loads a file into it.

SEE ALSO

RETURNS

NOTE
*/

/**/
Bitmap_C::Bitmap_C(char *fName)
{
Data=0;
OriginalPal.Pal=0;
OriginalPal.ColorsLoaded=0;
memset(&OriginalHeader,0,sizeof(BmpHeader_S));
Load(fName);
}

/**/
/*
Bitmap_C::Bitmap_C() Bitmap_C::Bitmap_C()

NAME
Bitmap_C::Bitmap_C() - Constructor

SYNOPSIS
Bitmap_C::Bitmap_C(unsigned long W, unsigned long H, unsigned char BD)
unsigned long W width
unsigned long H height
unsigned long BD bit-depth (color)

DESCRIPTION
Creates a new bitmap object with user specified attributes.

SEE ALSO

RETURNS

NOTE
*/

/**/
Bitmap_C::Bitmap_C(unsigned long W, unsigned long H, unsigned char BD)
{
Data=0;
OriginalPal.Pal=0;
OriginalPal.ColorsLoaded=0;
memset(&OriginalHeader,0,sizeof(BmpHeader_S));
Create(W,H,BD);
}

/**/
/*
Bitmap_C::~Bitmap_C() Bitmap_C::~Bitmap_C()

NAME
Bitmap_C::~Bitmap_C() - Destructor

SYNOPSIS
Bitmap_C::~Bitmap_C(void)

DESCRIPTION
Clears out memory, destructor for class.

SEE ALSO

RETURNS

NOTE
*/

/**/
Bitmap_C::~Bitmap_C(void)
{
Close();
}

/*********************************************************************************************/
/* this is a test app showing how to use this class.

//This can be used to plot points rather than doing so directly!
#define PlotPoint(Bmp,x,y,r,g,b)\
{\
unsigned long offset=y*Bmp.CurrentHeader.Width*3+x*3;\
Bmp.Data[offset++]=r;\
Bmp.Data[offset++]=g;\
Bmp.Data[offset]=b;\
}

int main(void)
{
Bitmap_C Bmp(32,32,24); // Create new bitmap. Width = 32, Height = 32, colordepth = 24
long x,y;
unsigned long off=0;

// Scan every row
for (y=0;y!=Bmp.CurrentHeader.Height;++y)
{
// Scan every pixel.
for (x=0;x!=Bmp.CurrentHeader.Width;++x)
{
Bmp.Data[off++]=x*8; // Set red to a value
Bmp.Data[off++]=y*8; // set green to a value
Bmp.Data[off++]=0; // set blue to a value
}
}

Bmp.Save("c:/Test.bmp",24); // Save results to disk.
return 0; // return non-error code.
}
*/

/*********************************************************************************************/


The commented out main shows an example on how it would be used to create a new bitmap 32x32x24, write a bit of color data to it, and write it out. I don''t currently support writing out anything but 24-bits, because I had no use for an 8-bit writer .
Dwiel
Dwiel
Unfortuantely I have no where neer $500 to spend (I am only in HS) and this project can only be considered reasearch so I am not going to have a sellable finsihe product... I would also like to distrubute my research as GPL... I don''t think I would be able to realease that portion of it anyway if I was going to allow people to download it for free.

Thanks for all of the responses.

Ready4Dis: Thanks for your bitmap class I am sure it will be useful, I REALLY REALLY hope to not have to spend the time to create this graphing though... and would like to do a GPL release... If anyone knows of a free API that I could use that would be terrific... I am becoming doubtful that such thing exists though... *sigh*... If anyone has some free time and would like to join my project: ZDGP.cvshome.org That would be wonderful

thanks for the help so far... I think I am going to look into using excel to graph it.. not free, but most ppl with windows will ahve it...

Thanks again!

Dwiel

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.