I'm an absolute noobie at C++ as I've only been familiar with Java programming. What I'm trying to do is to read an Image file (.bmp) into a matrix where I can perform a convolution with a 3x3 matrix (filter) on the matrix to produce a new image file with the convoluted image.
I've looked around google and managed to come up with the following implementation:
Image.h file:
// Image.h
#include <fstream> // for file I/O
using namespace std;
typedef unsigned char unchar; // Easier to understand & code.
class MImage {
public:
MImage(const char* fileName); //Constructor
~MImage(); //Deconstructor
void write(const char* fileName);
void smoothFilter(); //smoothing filer.
private:
ifstream* pInFile;
ofstream* pOutFile;
unchar imageHeaderData[1078]; //.bmp header data with offset 1078.
unchar** imageData;
unchar m_smoothFilter[3][3]; // Smoothing Filter.
unchar** filteredData;
};
Image.cpp file:
// Image.cpp
//
#ifndef _Image_h
#define _Image_h
#define WIDTH 128
#define HEIGHT 128
#include "Image.h"
#include <cmath>
#endif
using namespace std;
typedef unsigned char unchar;
//Constructor
MImage::MImage(const char* fileName){
imageData = new unchar* [HEIGHT]; // create new array size: height of image.
filteredData = new unchar* [HEIGHT];// create new array size: height of image.
for (int i = 0; i < HEIGHT; i++) {
imageData[i] = new unchar [WIDTH]; //create matrix.
filteredData[i] = new unchar [WIDTH]; //create matrix.
}
//image I/O
pInFile = new ifstream;
pInFile->open(fileName, ios::in | ios::binary); // open fileName and read as binary.
pInFile->seekg(0, ios::beg); //pos filter at beginning of image file.
pInFile->read(reinterpret_cast<char*>(imageHeaderData),1078); //read bmp header data into array.
for(int i=0; i<HEIGHT; i++) {
pInFile->read(reinterpret_cast<char*>(imageData[i]),WIDTH);//read row into each array entry.
}
pInFile->close(); //close stream.
char m_smoothFilter[3][3] = {
{1,1,1},
{1,2,1},
{1,1,1}
};
}
MImage::~MImage(){
delete pInFile;
delete pOutFile;
for(int i=0; i<HEIGHT; i++){
delete[] imageData[i];
delete[] filteredData[i];
}
delete[] imageData;
delete[] filteredData;
}
void MImage::write(const char* fileName) {
smoothFilter();
pOutFile = new ofstream;
pOutFile->open(fileName, ios::out | ios::trunc | ios::binary);
pOutFile->write(reinterpret_cast<char*>(imageHeaderData), 1078); //write header data onto output
for(int i = 0; i < HEIGHT; i++){
pOutFile->write(reinterpret_cast<char*>(filteredData[i]),WIDTH); // write new image data.
}
pOutFile->close(); //close stream
}
void MImage::smoothFilter(){
//copy input image into new image
for(int i = 0; i < HEIGHT; i++) {
strcpy(reinterpret_cast<char*>(filteredData[i]), reinterpret_cast<char*>(imageData[i]));
}
int sumOfPixels = 0;
for(int i = 1; i < HEIGHT -1; i++) {
for(int j = 1; j < WIDTH -1; j++) {
sumOfPixels = m_smoothFilter[0][0] * imageData[i+1][j-1] + // top left corner
m_smoothFilter[0][1] * imageData[i+1][j] + // top center
m_smoothFilter[0][2] * imageData[i+1][j+1] + // top right corner
m_smoothFilter[1][0] * imageData[i][j-1] + // center left
m_smoothFilter[1][1] * imageData[i][j] + // center center
m_smoothFilter[1][2] * imageData[i][j+1] + // center right
m_smoothFilter[2][0] * imageData[i-1][j-1] + // bottom left corner
m_smoothFilter[2][1] * imageData[i-1][j] + // bottom center
m_smoothFilter[2][2] * imageData[i-1][j+1]; // bottom right corner
filteredData[i][j] = (sumOfPixels / ( m_smoothFilter[0][0] + m_smoothFilter[0][1] +
m_smoothFilter[0][2] + m_smoothFilter[1][0] +
m_smoothFilter[1][1] + m_smoothFilter[1][2] +
m_smoothFilter[2][0] + m_smoothFilter[2][1] +
m_smoothFilter[2][2]));
}
}
}
Main.cpp file:
//
// Main.cpp
//
#include <iostream>
#include "Image.cpp"
#include <fstream>
using namespace std;
int main() {
MImage img("test.bmp");
img.write("output.bmp");
return 0;
}
When I try to run the following file with:
g++ Main.cpp -o main
./main
I get a segmentation:11 error and not sure what is causing this error!
Note: I have to use a pure C++ implementation so cannot use other libraries.
HELP!
EDIT: I think the code thats giving me the segmentation error is :
for(int i = 0; i < HEIGHT; i++) {
strcpy(reinterpret_cast<char*>(filteredData[i]), reinterpret_cast<char*>(imageData[i]));
}
But not sure why!
EDIT #3: Works after replacing above code with :
for(int i= 0; i<HEIGHT; i++) {
strncpy (reinterpret_cast<char*>(filteredData[i]),
reinterpret_cast<char*>(imageData[i]),
sizeof(reinterpret_cast<char*>(filteredData[i])));
}
replaced strcpy()
with strncpy()
which is much safer apparently and that removed the segmentation fault.