Thread: C++ Image Processing Homework (dynamic 2d array binary i/o trouble)

  1. #1
    Registered User
    Join Date
    Mar 2003
    Posts
    5

    Question C++ Image Processing Homework (dynamic 2d array binary i/o trouble)

    Well this is my first post on the board; hopefully I got the code tags right.

    For my advanced c++ course I had to write a program that read in a .bmp file that was 256 colors and 320x240 pixels.

    Here are the instructions:

    "Project #4
    Image Processing

    Write a C++ program to read an image and apply some statistical functions to it.
    Write your Image C++ class in a header file, and call an instance of it from the source file.

    1. Read an image
    2. Find the MEAN of the image
    3. Find the STDV of the image
    4. Apply the following filter to the image and write the output image to the disk.

    1 1 1
    1 2 1
    1 1 1

    5. Write the result buffer to an image."

    I managed to do all this but then he threw me a curve ball. He told us to dynamically allocate the buffers. I thought I knew how to do this but I was wrong apparently as I can't get it to work. If anyone can help me I would appreciate it.

    Below is the code I have written.

    file = Image.h

    Code:
    #include <fstream>
    
    using namespace std;
    
    typedef unsigned char uchar;
    
    class CImage
    {
    public:
    	CImage(const char* filename);
    	~CImage();
    	void write(const char* filename);
    	double mean();
    	double stdv();
    	void filter();
    
    private:
    
    	ifstream* m_pInFile;
    	ofstream* m_pOutFile;
    	uchar m_cHeaderData[1078];
    	uchar** m_cImageData;
    	uchar m_cFilter[3][3];
    	uchar** m_cFilteredData;
    };
    file = Image.cpp

    Code:
    #ifndef __IMAGE_H
    #define __IMAGE_H
    #define WIDTH	320
    #define HEIGHT	240
    
    #include "Image.h"
    #include <cmath>
    
    #endif
    
    using namespace std;
    
    typedef unsigned char uchar;
    
    ///////////////////////////////////////////////////////////////////////////////
    // Constructor
    ///////////////////////////////////////////////////////////////////////////////
    
    CImage::CImage(const char* filename)
    {
    	
    	m_cImageData = new uchar* [HEIGHT];
    	m_cFilteredData = new uchar* [HEIGHT];
    	for( int i = 0; i < HEIGHT; i++)
    	{
    		m_cImageData[i] = new uchar [WIDTH];
    		m_cFilteredData[i] = new uchar [WIDTH];
    	}
    	
    	m_pInFile = new ifstream;
    	m_pInFile->open(filename, ios::in | ios::binary);
    	m_pInFile->seekg(0, ios::beg);
    	m_pInFile->read(reinterpret_cast<char*>(m_cHeaderData[i]), 1078);
    	for( i = 0; i < HEIGHT; i++)
    	{
    	
    		m_pInFile->read(reinterpret_cast<char*>(m_cImageData[i]), WIDTH);
    
    	}
    
    	m_pInFile->close();
    	
    	// define the filter for the image
    	char m_cFilter[3][3] = {
    								{1, 1, 1},
    								{1, 2, 1},
    								{1, 1, 1}
    							};
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    // Destructor
    ///////////////////////////////////////////////////////////////////////////////
    
    CImage::~CImage()
    {
    	delete m_pInFile;
    	delete m_pOutFile;
    	for(int i = 0; i < HEIGHT; i++)
    	{
    		delete[] m_cImageData[i];
    		delete[] m_cFilteredData[i];
    	}
    	delete[] m_cImageData;
    	delete[] m_cFilteredData;
    
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    // Output the filtered image to a new bitmap file
    ///////////////////////////////////////////////////////////////////////////////
    
    void CImage::write(const char* filename)
    {
    
    	filter();
    	m_pOutFile = new ofstream;
    	m_pOutFile->open(filename, ios::out | ios::trunc | ios::binary);
    	m_pOutFile->write(reinterpret_cast<char*>(m_cHeaderData), 1078);
    	for(int i = 0; i < HEIGHT; i++)
    	{
    		m_pOutFile->write(reinterpret_cast<char*>(m_cFilteredData[i]), WIDTH);
    	}
    	m_pOutFile->close();
    	
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    // Calculate the mean of all the pixels
    ///////////////////////////////////////////////////////////////////////////////
    
    double CImage::mean()
    {
    	double total = 0;
    	for(int i = 0; i < HEIGHT; i++)
    	{
    		for(int j = 0; j < WIDTH; j++)
    		{
    			total += m_cImageData[i][j];
    		}
    	}
    	return (total / (HEIGHT * WIDTH));
    
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    // Calculate the standard deviation of all the pixels
    ///////////////////////////////////////////////////////////////////////////////
    
    double CImage::stdv()
    {
    	double avg = mean();
    	double radicand = 0;
    
    	for(int i = 0; i < HEIGHT; i++)
    	{
    		for(int j = 0; j < WIDTH; j++)
    		{
    			radicand += (m_cImageData[i][j] - avg) * (m_cImageData[i][j] - avg);
    		}
    	}
    
    	radicand /= (HEIGHT * WIDTH);
    	
    	return sqrt(radicand);
    }	
    
    ///////////////////////////////////////////////////////////////////////////////
    // Filter all the pixels
    ///////////////////////////////////////////////////////////////////////////////
    
    void CImage::filter()
    {
    	int sumofpixels = 0;
    
    	for(int i = 0; i < HEIGHT; i++)
    	{
    		strcpy(reinterpret_cast<char*>(m_cFilteredData[i]), reinterpret_cast<char*>(m_cImageData[i]));
    	}
    
    
    	for( i = 1; i < HEIGHT - 1; i++)
    	{
    		for(int j = 1; j < WIDTH - 1; j++)
    		{
    		
    			sumofpixels =	m_cFilter[0][0] * m_cImageData[i+1][j-1] + // top left corner
    							m_cFilter[0][1] * m_cImageData[i+1][j] + // top center
    							m_cFilter[0][2] * m_cImageData[i+1][j+1] + // top right corner
    							m_cFilter[1][0] * m_cImageData[i][j-1] + // center left
    							m_cFilter[1][1] * m_cImageData[i][j] + // center center
    							m_cFilter[1][2] * m_cImageData[i][j+1] + // center right
    							m_cFilter[2][0] * m_cImageData[i-1][j-1] + // bottom left corner
    							m_cFilter[2][1] * m_cImageData[i-1][j] + // bottom center
    							m_cFilter[2][2] * m_cImageData[i-1][j+1]; // bottom right corner
    			
    			m_cFilteredData[i][j] = (sumofpixels / (m_cFilter[0][0] + m_cFilter[0][1] +
    													m_cFilter[0][2] + m_cFilter[1][0] +
    													m_cFilter[1][1] + m_cFilter[1][2] +
    													m_cFilter[2][0] + m_cFilter[2][1] +
    													m_cFilter[2][2]) );
    		}
    	}
    }
    file = Project4.cpp

    Code:
    #include "Image.h"
    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    int main()
    {
    
    	CImage ci("test.bmp");
    	ci.write("output.bmp");
    	cout << ci.mean() << endl;
    	cout << ci.stdv() << endl;
    
    	return 0;
    }

  2. #2
    Registered User
    Join Date
    Mar 2003
    Posts
    5
    Another semi related question.

    I thought the scope of variables declared in the first part of a for loop was limited to that for loop but if I try a for( int i = 0; ...) and then another for( int i = 0; ...) in the same function I get an error so when do those variables cease to exist?

  3. #3
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    Code:
    for(int i = 0; i < HEIGHT; i++)
    	{
    		strcpy(reinterpret_cast<char*>(m_cFilteredData[i]), reinterpret_cast<char*>(m_cImageData[i]));
    	}
    
    
    	for(int i = 1; i < HEIGHT - 1; i++)
    >I thought the scope of variables declared in the first part of a for loop was limited to that for loop

    you are right, thats why when you use the 'i' in the second for loop, you need to declare it as an int again.

    what are the errors you are getting with the dynamic allocation?

  4. #4
    Registered User
    Join Date
    Mar 2003
    Posts
    5
    test the code... i use MSVC++ 6.0.

    I get no errors from the code I posted the problem is that the image that is output is not correct, not even readable by an image viewer program (paint for instance)

    if I use for(int i;...) in the 2nd for loop I get error C2374: 'i' : redefinition; multiple initialization

    ill attach an image if anyone wants to test it but is too lazy to open paint

  5. #5
    Registered User
    Join Date
    Mar 2003
    Posts
    5

    Smile

    AHAH I added the [i] to the m_pInFile->read(reinterpret_cast<char*>(m_cHeaderData) line by mistake when I was adding for loops to the static version of the program. It works now thank you.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem reading tiff image files?
    By compz in forum C++ Programming
    Replies: 9
    Last Post: 10-30-2009, 04:17 AM
  2. Simple Image Processing
    By ejohns85 in forum C++ Programming
    Replies: 4
    Last Post: 03-19-2009, 12:10 PM
  3. image processing
    By ICool in forum C Programming
    Replies: 75
    Last Post: 10-15-2007, 04:42 AM
  4. 2d to 3d: Image processing
    By arjunajay in forum C++ Programming
    Replies: 2
    Last Post: 07-19-2006, 09:39 PM
  5. Replies: 6
    Last Post: 03-03-2005, 03:52 AM