As part of my University assignment we are required to compare two images in the form of .txt one is the normal image, the other is a jumbled version of the image.
Both images are 512x512 and we are asked to consider that they have been broken into 16x16 blocks which means each block is 32x32.
To compare the two images i'm using a sum of squared differences algorithm on blocks of the image. Starting from the top left and working my way round until an appropriate math is found. However this is where my issue is occurring, after successfully taking a single block from the unjumbled image and comparing it to another block from the jumbled image, the second iteration causes the following error:
Windows has triggered a breakpoint in Assignment1.exe.
This may be due to a corruption of the heap, which indicates a bug in
Assignment1.exe or any of the DLLs it has loaded.
My question is what is causing the error in my code?
The following is my header file called Matrix.h it converts the 2d matrix obtained from the txt file to a 1d image.
#pragma
#ifndef MATRIX_H
#define MATRIX_H
class Matrix
{
protected:
int M;
int N;
double* data;
Matrix(){M = 0; N = 0;data = 0;} //Constructor to avoid error
public:
Matrix(int sizeR, int sizeC, double* input_data); //Constructor
Matrix(int sizeR, int sizeC);
~Matrix(); //Destructor
Matrix(const Matrix& existingMatrix); //Copy Constructor
double get (int i , int j) const; //Returns value at specified location
const void set(int i, int j, double& val); //Changes value at specified location
int getM() const; //Return value of M
int getN() const; //Return value of N
Matrix getBlock(int startRow, int endRow, int startColumn, int endColumn); //Return section of Matrix
Matrix operator + (const Matrix& B);
Matrix operator = (const Matrix& B);
Matrix operator - (const Matrix& B);
Matrix operator * (const Matrix& B);
Matrix operator / (const Matrix& B);
Matrix operator ++ ();
double operator () (int i, int j);
void out();
double sum();
};
class BinaryImage
:public Matrix
{
public:
BinaryImage(int sizeR, int sizeC, double* input_data, double thresh);
~BinaryImage();
BinaryImage(const Matrix& rhs, double thresh);
BinaryImage(const BinaryImage& existingBinIm);
const void set(int i, int j, double& val);
};
#endif
This next section is my Main, the method we are using in the case of the error is called shuffledLogo().
#include<iostream>
#include<Windows.h>
#include<fstream>
#include<string>
#include"Matrix.h"
using namespace std;
void shuffledLogo();
double* readTXT(char* fileName, int sizeR, int sizeC);
void writePGM(char* fileName, Matrix& toWrite, int Q);
int main()
{
int selection;
cout<<"Select a program to run:"<<endl<<"1 - Logo Reorganisation"<<endl<<"2 - Where's Wally"<<endl<<"Selection: ";
cin>>selection;
cout<<endl;
switch(selection)
{
case 1:
cout<<"Logo Reorganisation Commencing..."<<endl;
shuffledLogo();
break;
case 2:
cout<<"Where's Wally Commencing..."<<endl;
break;
default:
cout<<"Selection invalid"<<endl;
break;
}
Sleep(1000);
return 0;
}
//Consructor
Matrix::Matrix(int sizeR, int sizeC, double* inputData)
{
M = sizeR;
N = sizeC;
data = new double [M*N];
for (int ii = 0; ii < M*N; ii++)
{
data[ii] = inputData[ii];
}
}
Matrix::Matrix(int sizeR, int sizeC)
{
M = sizeR;
N = sizeC;
data = new double [M*N];
for (int ii = 0; ii < M*N; ii++)
{
*(data+ii) = 0;
}
}
//Destructor
Matrix::~Matrix()
{
delete [] data;
}
//Copy Constructor
Matrix::Matrix(const Matrix& existingMatrix)
{
M = existingMatrix.getM();
N = existingMatrix.getN();
data = new double[M*N];
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
int k = ii*N+jj;
data[k] = existingMatrix.get(ii,jj);
}
}
}
//Pass by constant value
double Matrix::get (int i , int j) const
{
int k = i*N + j;
return data[k];
}
//Pass by Refrence
const void Matrix::set(int i, int j, double& val)
{
int k = i*N + j;
val = data[k];
}
//Return Value of M
int Matrix::getM() const
{
return M;
}
//Return Value of N
int Matrix::getN() const
{
return N;
}
//Return Section of the Matrix.
Matrix Matrix::getBlock(int startRow, int endRow, int startColumn, int endColumn)
{
int Row = endRow-startRow;
int Column = endColumn - startColumn;
double* block = new double[(Row)*(Column)];
int n = endColumn-startColumn;
for (int ii = startRow; ii < endRow; ii++)
{
for (int jj = startColumn; jj < endColumn; jj++)
{
int k = ii*n+jj;
block[k] = data[ii*N+jj];
}
}
Matrix t(Row,Column,block);
delete [] block;
return t;
}
//Allows for addion of Matricies, Operation Overloading.
Matrix Matrix::operator +(const Matrix& B)
{
Matrix C = Matrix(M, N, 0);
double temp;
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
temp = data[ii*N+jj] + B.get(ii,jj);
C.set(ii,jj, temp);
}
}
return C;
}
//Makes x and y equal, Opperation Overloading.
Matrix Matrix::operator =(const Matrix& B)
{
if (this == &B)
{
return *this;
}
else
{
M = B.getM();
N = B.getN();
delete [] data;
data = new double [M*N];
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
data[ii*N+jj] = B.get(ii,jj);
}
}
return *this;
}
}
//Allows for subtraction of matricies, Operation Overloading.
Matrix Matrix::operator -(const Matrix& B)
{
Matrix C = Matrix(M, N);
double temp;
for (int ii = 0; ii < M-1; ii++)
{
for (int jj = 0; jj < N-1; jj++)
{
temp = data[ii*N+jj] - B.get(ii,jj);
C.set(ii,jj, temp);
}
}
return C;
}
//Allows for multiplication of Matricies, Operation Overloading.
Matrix Matrix::operator *(const Matrix& B)
{
Matrix C = Matrix(M, B.getN());
double temp;
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
temp = data[ii*N+jj] * B.get(ii,jj);
C.set(ii,jj, temp);
}
}
return C;
}
//Allows for addition of Matricies, Operation Overloading.
Matrix Matrix::operator /(const Matrix& B)
{
Matrix C = Matrix(M, B.getN(), 0);
double temp;
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
temp = data[ii*N+jj] / B.get(ii,jj);
C.set(ii,jj, temp);
}
}
return C;
}
//Incrmentation of all values in Matrix by 1, Operation Overloading.
Matrix Matrix::operator ++()
{
for (int ii = 0; ii < M*N; ii++)
{
data[ii] = data[ii]++;
}
return *this;
}
//Allows calling of "get" function indirectly.
double Matrix::operator() (int i, int j)
{
return data[i*N+j];
}
double Matrix::sum()
{
double total = 0.0;
for (int ii = 0; ii < M*N; ii++)
{
total = total + data[ii];
}
return total;
}
void Matrix::out()
{
for (int ii = 0; ii < M*N; ii++)
{
if(data[ii] == 255)
cout<<"1 ";
else
cout<<data[ii]<<" ";
}
}
BinaryImage ::BinaryImage(int sizeR, int sizeC, double*input_data, double thresh)
:Matrix(sizeR, sizeC, input_data)
{
for(int ii = 0; ii < M*N; ii++)
{
if (data[ii] > thresh)
{
data[ii] = 1;
}
else
{
data[ii] = 0;
}
}
}
BinaryImage::BinaryImage(const Matrix& rhs, double thresh)
:Matrix(rhs)
{
for(int ii = 0; ii < M*N; ii++)
{
if (data[ii] > thresh)
{
data[ii] = 1;
}
else
{
data[ii] = 0;
}
}
}
BinaryImage::BinaryImage(const BinaryImage& rhs)
{
M = rhs.getM();
N = rhs.getN();
data = new double[M*N];
for (int ii = 0; ii<M; ii++){
for (int jj = 0; jj<N; jj++){
data[ii] = rhs.get(ii, jj);
}
}
}
const void BinaryImage::set(int i, int j, double& val)
{
int k = i*N + j;
val = data[k];
}
void shuffledLogo()
{
char* filePath2 = "E:\\logo_shuffled.txt";
double* basIm2 = readTXT(filePath2, 512, 512);
Matrix logoWithNoise(512, 512, basIm2);
cout<<"done"<<endl;
//Reads in the Shuffled Image
char* filePath = "E:\\logo_shuffled.txt";
double* basIm = readTXT(filePath, 512, 512);
Matrix logoShuffled(512, 512, basIm);
cout<<"done"<<endl;
Matrix logoUnshuffled(512,512);
double Score = 0.0; //Current "Pixels" score
double bestScore = 0.0; //Best "Pixel" score
int bestX, bestY = 0;
//For Loop to begin Sum of Squared Differences
for (int x = 0; x < 480; x+=32)
{
for (int y = 0; y < 480; y += 32)
{
Matrix subWithNoise = logoWithNoise.getBlock(x,(x+32),y,(y+32));
//subShuffled.out();
bestScore = 70000.0;
for (int xx = 0; xx< 480; xx+=32)
{
for (int yy = 0; yy < 480; yy+=32)
{
//Calculating the Score starts here
cout<<"loop started"<<endl;
int t = yy+32;
int l = xx+32;
Matrix subShuffled = logoShuffled.getBlock(xx,l, yy, t);
cout<<"submade"<<endl;
Matrix diff = subWithNoise - logoWithNoise;
Matrix product = diff*diff;
Score = diff.sum();
if (Score < bestScore)
{
bestScore = Score;
bestX = xx;
bestY = yy;
}
cout<<"loop ended"<<endl;
}
}
//For loop to put the best option into the final Matrix
for (int ii = bestX; ii < (bestX+=32); ii++)
{
for (int jj = bestY; jj < (bestY+=32); jj++)
{
double temp = logoShuffled.get(ii,jj);
logoUnshuffled.set(ii,jj,temp);
}
}
}
}
//Creates file
char* newFile = "finished.pgm";
writePGM(newFile, logoUnshuffled, 1);
}
//Reads in file and from specified location and builds it
double* readTXT(char* fileName, int sizeR, int sizeC)
{
double* input_data = new double[sizeR*sizeC];
int i =0;
ifstream currentFile(fileName);
if (currentFile.is_open())
{
while(currentFile.good())
{
if (i>sizeR*sizeC-1) break;
currentFile >> *(input_data+i);
i++;
}
currentFile.close();
}
else
{
cout<<"File path not found"<<endl;
}
return input_data;
delete [] input_data;
}
void writePGM(char* fileName, Matrix& toWrite, int Q)
{
int x = toWrite.getM();
int y = toWrite.getN();
unsigned char *image;
ofstream myfile;
image = (unsigned char *) new unsigned char [x*y];
// convert the integer values to unsigned char
for(int i = 0; i<x; i++)
{
for (int j = 0; j<y; j++)
{
image[i*y+j]=(unsigned char)toWrite.get(i,j);
}
}
myfile.open(fileName, ios::out|ios::binary|ios::trunc);
if (!myfile)
{
cout << "Can't open file: " << fileName << endl;
exit(1);
}
myfile << "P5" << endl;
myfile << y << " " << x << endl;
myfile << Q << endl;
myfile.write( reinterpret_cast<char *>(image), (x*y)*sizeof(unsigned char));
if (myfile.fail())
{
cout << "Can't write image " << fileName << endl;
exit(0);
}
myfile.close();
delete [] image;
}
I have taken the liberty of placing my folders in a public dropbox file for you to all see if you'd like to get a better look at the error. I understand that my code might be messy and poorly displayed so if anyone has any suggestions on how to make it better please say.
Dropbox to program files
Related
I have a University assignment whereby I have a 1D array, containing 262144 values. I've created a matrix class which places these values into an object with the datasource being the double* list of 262144 values.
I need to be able to obtain a sub-matrix (which I'm able to do) from ANOTHER set of 262144 values (which I've also placed into a matrix object).
However, I'm having serious trouble and I've been trying so hard for the last 3 days to try and replace original matrix values from a sub-matrix. I've tried passing by reference, creating Matrix*'s. I've tried everything we've been taught and even researched a few more methods, all of which I haven't understood. I'll throw my code in here to see if anyone can explain a method to me which will be able to do this.
Matrix::Matrix()
{
"Matrix::Matrix() is invoked";
}
Matrix::Matrix(const Matrix& m)
{
"Matrix::Matrix(const Matrix&) is invoked";
_M = m._M;
_N = m._N;
_data = new double[_M*_N];
for (int i = 0; i < _M*_N; i++)
{
_data[i] = m._data[i];
}
}
Matrix::Matrix(int sizeR, int sizeC, double *input_data)
{
"Matrix::Matrix(int sizeR, int sizeC, double *input_data is invoked";
_M = sizeR;
_N = sizeC;
_data = new double[_M*_N];
for (int i = 0; i < _M*_N; i++)
{
_data[i] = input_data[i];
}
}
Matrix Matrix::get_Block(int start_row, int end_row, int start_coloumn, int end_coloumn)
{
int rows = (end_row - start_row);
int columns = (end_coloumn - start_coloumn);
int ctr = 0;
double *temp_Data = new double[rows*columns];
for (int x = start_row; x < (rows + start_row); x++)
{
for (int y = start_coloumn; y < (columns + start_coloumn); y++)
{
temp_Data[ctr] = get(x, y);
ctr++;
}
}
Matrix block(rows, columns, temp_Data);
delete[] temp_Data;
return block;
}
Matrix Matrix::operator+(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] + other._data[x];
}
return temp;
}
Matrix Matrix::operator*(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] * other._data[x];
}
return temp;
}
Matrix Matrix::operator-(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] - other._data[x];
}
return temp;
}
void Matrix::replace_Block(Matrix& noisy, Matrix& shuffled,int k, int j, int i)
{
int val_to_replace = 0;
for (int i = 0; i < 3 * 3; i++)
{
val_to_replace = shuffled.get(i, j);
noisy.set(i, j, val_to_replace);
}
}
void Matrix::set_Block(Matrix block, Matrix& Noisy, int start_row, int end_row)
{
int ctr = 0;
int ctr2 = 0;
int ctr3 = 0;
for (int i = 0; i < 3; i++)
{
Noisy._data[(start_row*_M)+i+4] = block.get(i, ctr);
ctr++;
}
for (int j = 0; j < 3; j++)
{
Noisy._data[((start_row + 1)*_M) + j + 3] = block.get(j, ctr2);
ctr2++;
}
for (int j = 0; j < 3; j++)
{
Noisy._data[((start_row + 1)*_M) + j + 2] = block.get(j, ctr3);
ctr3++;
}
}
double Matrix::get_Sum(Matrix m)
{
double total = 0;
short row = m.get_M();
short column = m.get_N();
for (int j = 0; j < row; j++)
{
for (int i = 0; i < column; i++)
{
total += m.get(j,i);
}
}
return total;
}
double Matrix::get_Sum(Matrix* m)
{
double total = 0;
short row = m->get_M();
short column = m->get_N();
for (int j = 0; j < row; j++)
{
for (int i = 0; i < column; i++)
{
total += m->get(i, j);
}
}
return total;
}
double Matrix::get(int i, int j)
{
return _data[(i * _M) + j];
}
void Matrix::write_Block(int i, int j)
{
for (int ctr = 0; ctr < i; ctr++)
{
for (int ctr2 = 0; ctr2 < j; ctr2++)
{
std::cout << " " << this->get(ctr,ctr2);
}
std::cout << std::endl;
}
}
void Matrix::set(int i, int j, double val)
{
this->_data[(i*_M) + j] = val;
}
void Matrix::set_N(int N)
{
_N = N;
}
void Matrix::set_M(int M)
{
_M = M;
}
int Matrix::get_N()
{
return _N;
}
int Matrix::get_M()
{
return _M;
}
Matrix::~Matrix()
{
"Matrix::~Matrix() is invoked";
delete[] _data;
}
If it would be helpful to see main() I can supply that too, however all it really contains is the creation of the matrix objects using overloaded constructors.
explanation
Answer is only 4 years late . . .
Anyway. Maybe it will help somebody else. The secret is to use a std::valarray. With that it is utmost simple to work on a matrix. And, many many functions are available.
All the functions that you want to implement are already available.
And you sub-matrix coy can be a one liner . . .
Please see example code:
#include <iostream>
#include <algorithm>
#include <numeric>
#include <valarray>
#include <iomanip>
constexpr size_t NRows = 6;
constexpr size_t NCols = 8;
constexpr size_t SubNRows = 2;
constexpr size_t SubNCols = 3;
void debugPrint(std::valarray<int> &v, size_t nrows = NRows, size_t ncols = NCols)
{
for (int r = 0; r < nrows; ++r) {
for (int c = 0; c < ncols; ++c)
std::cout << std::setw(3) << v[r*ncols+c] << ' ';
std::cout << '\n';
}
std::cout << '\n';
}
int main()
{
std::valarray<int> v1(NRows * NCols); // Define array with given size
std::iota(std::begin(v1),std::end(v1),0); // Fill the array with consecutive nunbers
debugPrint (v1); // Print the result
std::cout << "\nSum = " << v1.sum() << "\n\n"; // Print the sum of all values in matrix
std::valarray<int> v2(v1); // Create a 2nd matrix as a copy to the first
v2 += 100; // Add 100 to each value in the matrix
debugPrint(v2);
std::valarray<int> v3(NCols); // Get one column
v3 = v1[std::slice(2,NRows,NCols)];
debugPrint(v3,NRows,1);
std::valarray<int> subV2(SubNRows*SubNCols); // So, now the sub array
subV2 = v2[std::gslice(12,{SubNRows, SubNCols},{NCols,1})]; // Slice it out
debugPrint(subV2, SubNRows, SubNCols);
v1[std::gslice(25,{SubNRows, SubNCols},{NCols,1})] = subV2; // And copy to the first array
debugPrint (v1);
return 0;
}
I'm trying to return a sub-image from a 5x7 matrix. I'm trying to retrieve the sub matrix (0,2,0,2). I've created a function get_Block which SHOULD return the values of the matrix to temp, however just getting:
Exception thrown at 0x003B2A96 in Logo_Unscrambler.exe: 0xC0000005: Access violation reading location 0xCCCCCCCC.
It's probably super simple but I'm mega tired and I can't see it. Here's the code:
Main:
int main() {
double* A = new double[5*7];
for (int i = 0; i < 5 * 7; i++)
{
A[i] = i;
}
Matrix Ab(5, 7, A);
Matrix temp;
temp = Ab.get_Block(0, 2, 0, 2);
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < 3; i++)
{
cout << " " << temp.get(k,i, 3);
}
cout << endl;
}
system("pause");
return 0;
}
Matrix.cpp:
Matrix::Matrix(int sizeR, int sizeC, double *input_data)
{
"Matrix::Matrix(int sizeR, int sizeC, double *input_data is invoked";
_M = sizeR;
_N = sizeC;
_data = new double[_M*_N];
for (int i = 0; i < _M*_N; i++)
{
_data[i] = input_data[i];
}
}
Matrix Matrix::get_Block(int start_row, int end_row, int start_coloumn, int end_coloumn)
{
int rows = (end_row - start_row) + 1;
int columns = (end_coloumn - start_coloumn) + 1;
int ctr = 0;
double *temp_Data = new double[rows*columns];
for (int x = start_row; x < (rows + start_row); x++)
{
for (int y = start_coloumn; y < (columns + start_coloumn); y++)
{
temp_Data[ctr] = get(x, y,rows);
ctr++;
}
}
Matrix block(rows, columns, temp_Data);
delete[] temp_Data;
return block;
}
double Matrix::get(int i, int j, int row_Count)
{
return _data[(i*_N) + j];
}
This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 7 years ago.
I am writing simple C++ application to multiply two matrices. Yes, I am aware this version doesn't check e.g. whether number of rows is greater than zero.
I can create two objects using a default constructor and I can create third object (a result of multiplication of two previous objects of the same class). I can't however correctly delete this third object. When I try, an "Access violation reading location" exception is throw. Can you tell me what am I missing? Is there something I forget to initialize? This exception is only thrown when using myThirdFunction.
Any other advice on making this code better is welcome :)
#include <iostream>
#include <ctime>
#include <iomanip>
using namespace std;
class MyArray
{
int Variable1 = 0;
int Variable2 = 0;
float ** myArray;
public:
MyArray() : Variable1(0), Variable2(0){ myFunction(); }
MyArray (int variable1, int variable2) : Variable1(variable1):
Variable2(variable2){ myFunction(); }
MyArray(const MyArray &myArrayA, const MyArray &myArrayB) :
Variable1(myArrayA.Variable1), Variable2(myArrayB.Variable2)
{ myThirdFunction(myArrayA, myArrayB); }
MyArray(const MyArray &myArray)
{ Variable1=myArray.Variable1; Variable2 = myArray.Variable2;
this->myArray =myArray.myArray; }
void myFunction() {
cin >> Variable1;
cin >> Variable2;
myArray = new float*[Variable1];
myOtherFunction();
}
void myOtherFunction() {
for (int i = 0; i < Variable1; ++i)
{
myArray[i] = new float[Variable2];
for (int j = 0; j < Variable2; ++j)
myArray[i][j] = rand() % (10 - 0) + 0;
}
}
void myThirdFunction(MyArray myArrayA, MyArray myArrayB)
{
Variable1 = myArrayA.Variable1;
Variable2 = myArrayB.Variable2;
myArray = new float*[Variable1];
for (int i = 0; i < Variable1; ++i)
{
myArray[i] = new float[Variable2];
for (int j = 0; j < Variable2; ++j)
{
float tempVariable = 0;
for (int q = 0; q < myArrayA.Variable2; ++q)
{
tempVariable += myArrayA.myArray[i][q] * myArrayB.myArray[q][j];
}
myArray[i][j] = tempVariable;
}
}
}
void displayMyArray() {
for (int i = 0; i < Variable1; ++i)
{
for (int j = 0; j < Variable2; ++j)
cout << myArray[i][j] << '\t';
cout << endl;
}
}
~MyArray() {
for (int i = 0; i < Variable1; ++i)
{
delete[] myArray[i];
}
delete[]myArray;
}
};
int main(){
srand(time(0));
MyArray myArrayA;
myArrayA.displayMyArray();
cout << endl;
MyArray myArrayB;
myArrayB.displayMyArray();
cout << endl;
MyArray myArrayC(myArrayA, myArrayB);
myArrayC.displayMyArray();
getchar();
getchar();
return 0;
}
Thanks :)
The member myArray is a pointer, and in your copy constructor you just copy the pointer without creating a new array. Because myThirdFunction takes both arguments by value, it creates two copies of the original objects. And because the copy constructor doesn't create a new value, when those two copies go out of scope at the end of the function, the original pointers now point to deallocated memory. Whenever the original two objects are destroyed, the destructor tries to delete memory that was already deleted.
From the beginning, you have this constructor:
MyArray(const MyArray &myArrayA, const MyArray &myArrayB)
{
myThirdFunction(myArrayA, myArrayB); //This call creates two new objects
}
The signature of myThirdFunction being void myThirdFunction(MyArray myArrayA, MyArray myArrayB), you pass by value and create two new copies. That calls the copy constructors for the two parameters:
MyArray(const MyArray &myArray)
{
this->myArray =myArray.myArray; //shallow copy, very bad
}
The new objects now point to the same memory as the originals. So, when they are destroyed at the end of myThirdFunction, the original pointers become garbage. In a broad view, this happens. float* p = new float; delete p; delete p; The solution is to make the copy constructor actually copy the elements, not the pointers:
MyArray(const MyArray &p_copy) //The name confused me so I changed it
{
Variable1 = p_copy.Variable1;
Variable2 = p_copy.Variable2;
myArray new float*[Variable1];
for (int i = 0; i < Variable1; ++i)
{
myArray[i] = new float[Variable2];
for (int j = 0; j < Variable2; ++j)
myArray[i][j] = p_copy.myArray[i][j];
}
}
In addition, you probably want to pass to myThirdFunction by constant reference.
void myThirdFunction(const MyArray& myArrayA, const MyArray& myArrayB)
I don't see a need to create two temporary objects here.
At the first time this code will works.
#include <iostream>
#include <ctime>
#include <iomanip>
using namespace std;
class MyArray
{
int Variable1;
int Variable2;
float ** myArray;
public:
MyArray() : myArray(NULL), Variable1(0), Variable2(0) // initialize pointers with NULL is important
{
myFunction();
}
MyArray (int variable1, int variable2) : myArray(NULL), Variable1(variable1),
Variable2(variable2)
{
myFunction();
}
MyArray(const MyArray &myArrayA, const MyArray &myArrayB) : myArray(NULL),
Variable1(myArrayA.Variable1), Variable2(myArrayB.Variable2)
{
myThirdFunction(myArrayA, myArrayB);
}
MyArray(const MyArray &myArray)
{
Variable1=myArray.Variable1; Variable2 = myArray.Variable2;
this->myArray =myArray.myArray;
}
void myFunction()
{
cin >> Variable1;
cin >> Variable2;
myArray = new float*[Variable1];
myOtherFunction();
}
void myOtherFunction()
{
for (int i = 0; i < Variable1; ++i)
{
myArray[i] = new float[Variable2];
for (int j = 0; j < Variable2; ++j)
myArray[i][j] = rand() % (10 - 0) + 0;
}
}
void myThirdFunction(MyArray myArrayA, MyArray myArrayB)
{
// cols of first must be same as rows of second
if (myArrayA.Variable2 != myArrayB.Variable1)
return;
// memory must be cleaned before new array creation
clearArray();
Variable1 = myArrayA.Variable1;
Variable2 = myArrayB.Variable2;
myArray = new float*[Variable1];
for (int i = 0; i < Variable1; ++i)
{
myArray[i] = new float[Variable2];
for (int j = 0; j < Variable2; ++j)
{
float tempVariable = 0;
for (int q = 0; q < myArrayA.Variable2; ++q)
{
tempVariable += myArrayA.myArray[i][q] * myArrayB.myArray[q][j];
}
myArray[i][j] = tempVariable;
}
}
}
void displayMyArray()
{
for (int i = 0; i < Variable1; ++i)
{
for (int j = 0; j < Variable2; ++j)
cout << myArray[i][j] << '\t';
cout << endl;
}
}
~MyArray()
{
clearArray();
}
// clear memory and deinitialize pointers
void clearArray()
{
if (myArray == NULL)
return;
for (int i = 0; i < Variable1; ++i)
{
delete[] myArray[i];
myArray[i] = NULL;
}
delete[]myArray;
myArray = NULL;
}
};
int main(){
srand(time(0));
MyArray myArrayA;
myArrayA.displayMyArray();
cout << endl;
MyArray myArrayB;
myArrayB.displayMyArray();
cout << endl;
MyArray myArrayC(myArrayA, myArrayB);
myArrayC.displayMyArray();
getchar();
getchar();
return 0;
}
but I strongly recomend you to create proper copy constructor and assignment operator means (operator=) to proper object creation and destruction.
Here I post my own matrix realization to refer you in what way you can approve your code.
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
using namespace std::
class Matrix
{
public:
Matrix();
Matrix(int rowcount,int colcount);
Matrix(int rowcount,int colcount,float* matrix);
Matrix(const Matrix& rhs);
~Matrix();
/////////////////////////////////////////////////////////////
Matrix& operator = (const Matrix& rhs);
Matrix operator + (const Matrix& rhs);
Matrix operator - (const Matrix& rhs);
Matrix operator * (float scale);
Matrix operator * (const Matrix& rhs);
void operator += (const Matrix& rhs);
void operator -= (const Matrix& rhs);
void operator *= (float scale);
void operator *= (const Matrix& rhs);
float operator [] (int offset) const;
float& operator [] (int offset);
friend ostream& operator << (ostream& _str,const Matrix& rhs);
/////////////////////////////////////////////////////////////
void setCols(int cols);
void setRows(int rows);
void setMatrix(float* matrix);
int getCols() const
{
return itsCols;
}
int getRows() const
{
return itsRows;
}
const float* getMatrix() const
{
Invariants();
return itsMatrix;
}
void Invariants() const
{
if ((!(itsCols && itsRows && itsMatrix)) && (itsRows < 0) && (itsCols < 0))
{
cout << "Not allowed action!\n";
getch();
exit(0);
}
}
/////////////////////////////////////////////////////////////
private:
float* itsMatrix;
int itsRows;
int itsCols;
};
Matrix::Matrix()
{
itsRows = 0;
itsCols = 0;
itsMatrix = NULL;
}
Matrix::Matrix(int rowcount,int colcount)
{
itsRows = rowcount;
itsCols = colcount;
itsMatrix = new float[itsRows * itsCols];
Invariants();
}
Matrix::Matrix(int rowcount,int colcount,float* matrix)
{
itsRows = rowcount;
itsCols = colcount;
itsMatrix = new float[itsCols * itsRows];
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
itsMatrix[counter] = matrix[counter];
counter++;
}
}
Invariants();
}
Matrix::Matrix(const Matrix& rhs)
{
itsCols = rhs.getCols();
itsRows = rhs.getRows();
itsMatrix = new float[itsRows * itsCols];
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
itsMatrix[counter] = rhs[counter];
counter++;
}
}
}
Matrix::~Matrix()
{
itsCols = 0;
itsRows = 0;
delete [] itsMatrix;
itsMatrix = NULL;
}
Matrix& Matrix::operator = (const Matrix& rhs)
{
if (&rhs == this)
return *this;
else
{
itsRows = rhs.getRows();
itsCols = rhs.getCols();
delete [] itsMatrix;
itsMatrix = NULL;
itsMatrix = new float[itsRows * itsCols];
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
itsMatrix[counter] = rhs[counter];
counter++;
}
}
return *this;
}
}
float& Matrix::operator [] (int offset)
{
Invariants();
if ((offset > -1) && (offset < itsCols * itsRows))
return itsMatrix[offset];
else
{
cout << "You cann't reach this element!\n";
getch();
exit(0);
}
return itsMatrix[offset];
}
float Matrix::operator [] (int offset) const
{
Invariants();
if ((offset > -1) && (offset < itsCols * itsRows))
return itsMatrix[offset];
else
{
cout << "You cann't reach this element!\n";
getch();
exit(0);
}
return 0;
}
Matrix Matrix::operator + (const Matrix& rhs)
{
Invariants();
if (!((this->itsCols == rhs.getCols()) &&
(this->itsRows == rhs.getRows())))
{
cout << "Cann't perform addiction of matrixes!\n";
getch();
exit(0);
}
Matrix temp(itsRows,itsCols);
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
temp[counter] = itsMatrix[counter] + rhs[counter];
counter++;
}
}
return temp;
}
Matrix Matrix::operator - (const Matrix& rhs)
{
Invariants();
if (!((this->itsCols == rhs.getCols()) &&
(this->itsRows == rhs.getRows())))
{
cout << "Cann't perform substraction of matrixes!\n";
getch();
exit(0);
}
Matrix temp(itsRows,itsCols);
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
temp[counter] = itsMatrix[counter] - rhs[counter];
counter++;
}
}
return temp;
}
Matrix Matrix::operator * (float scale)
{
Invariants();
Matrix temp(itsRows,itsCols);
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
temp[counter] = itsMatrix[counter] * scale;
counter++;
}
}
return temp;
}
Matrix Matrix::operator * (const Matrix& rhs)
{
Invariants();
if (!(itsCols == rhs.getRows()))
{
cout << "Cann't perform multiplication of matrixes!\n";
getch();
exit(0);
}
Matrix temp(itsRows,rhs.getCols());
int counter = 0;
float sum = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < rhs.getCols(); j++)
{
for (int k = 0; k < itsCols; k++)
{
sum += itsMatrix[i * itsCols + k] *
rhs[k * rhs.getCols() + j];
}
temp[counter] = sum;
sum = 0;
counter++;
}
}
return temp;
}
void Matrix::operator += (const Matrix& rhs)
{
if (!((this->itsCols == rhs.getCols()) &&
(this->itsRows == rhs.getRows())))
{
cout << "Cann't perform addiction of matrixes!\n";
getch();
exit(0);
}
Matrix temp(itsRows,itsCols);
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
temp[counter] = itsMatrix[counter] + rhs[counter];
counter++;
}
}
*this = temp;
}
void Matrix::operator -= (const Matrix& rhs)
{
if (!((this->itsCols == rhs.getCols()) &&
(this->itsRows == rhs.getRows())))
{
cout << "Cann't perform substraction of matrixes!\n";
getch();
exit(0);
}
Matrix temp(itsRows,itsCols);
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
temp[counter] = itsMatrix[counter] - rhs[counter];
counter++;
}
}
*this = temp;
}
void Matrix::operator *= (float scale)
{
Invariants();
Matrix temp(itsRows,itsCols);
int counter = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < itsCols; j++)
{
temp[counter] = itsMatrix[counter] * scale;
counter++;
}
}
*this = temp;
}
void Matrix::operator *= (const Matrix& rhs)
{
Invariants();
if (!(itsCols == rhs.getRows()))
{
cout << "Cann't perform multiplication of matrixes!\n";
getch();
exit(0);
}
Matrix temp(itsRows,rhs.getCols());
int counter = 0;
float sum = 0;
for (int i = 0; i < itsRows; i++)
{
for (int j = 0; j < rhs.getCols(); j++)
{
for (int k = 0; k < itsCols; k++)
{
sum += itsMatrix[i * itsCols + k] *
rhs[k * rhs.getCols() + j];
}
temp[counter] = sum;
sum = 0;
counter++;
}
}
*this = temp;
}
ostream& operator << (ostream& _str,const Matrix& rhs)
{
rhs.Invariants();
int counter = 0;
for (int i = 0; i < rhs.getRows(); i++)
{
for (int j = 0; j < rhs.getCols(); j++)
{
_str << rhs[counter] << "\t";
counter++;
}
_str << endl;
}
return _str;
}
float arr1[] =
{
2, 2, 2,
-1, -3, -5,
16, 8, 24,
8, 0, 16
};
float arr2[] =
{
15,
2,
-4
};
int main()
{
clrscr();
Matrix m1(4,3,arr1);
Matrix m2(3,1,arr2);
cout << "Matrix 1:\n";
cout << m1 << endl;
cout << "Matrix 2:\n";
cout << m2 << endl;
cout << "Matrix 1 * Matrix 2\n";
cout << m1 * m2 << endl;
getch();
cout << "Matrix 1 + Matrix 1\n";
cout << m1 + m1 << endl;
getch();
cout << "Matrix 1 - Matrix 1\n";
cout << m1 - m1 << endl;
getch();
cout << "Matrix 1 * 4\n";
cout << m1 * 4 << endl;
getch();
return 0;
}
class Matrix{
double **val;
int rows,cols,errorCode;
public:
Matrix();
Matrix(int);
Matrix(int, int);
~Matrix();
void Print();
void Read();
double Get(int, int);
void Assign(int,int,double);
void Addition(Matrix&);
void Subtraction(Matrix&);
Matrix Multiply(Matrix&);
void Multiply(double);
};
Matrix::Matrix(){
//First array go with rows.
val = new double*[1];
val[1] = new double[1];
rows = 1;
cols = 1;
errorCode = 0;
}
Matrix::Matrix(int n){
rows = n;
cols = n;
val = new double*[rows];
for(int i = 0;i<rows;i++){
val[i] = new double[cols];
}
}
Matrix::Matrix(int n,int m){
rows = n;
cols = m;
val = new double*[rows];
for(int i = 0;i<rows;i++){
val[i] = new double[cols];
}
}
Matrix::~Matrix(){
for(int i=0;i<rows;i++){
delete[] val[i];
}
delete[] val;
}
Matrix Matrix::Multiply(Matrix &a){
if(cols != a.rows){
Matrix b;
b.errorCode=111; //That means dimensions are not valid;
return b;
}
else{
Matrix b(rows,a.cols);
double p;
for(int i=0;i<rows;i++){
for(int j=0;j<a.cols;j++){
p=0;
for(int k=0;k<cols;k++){p += val[i][k]*a.val[k][j];}
b.Assign(i,j,p);
}
}
return b;
}
}
When i compile it seems to be ok, but when i run it doesn't work and i don't understand why...it says "program stoped worked" and returned error 255
If needed i can put all the code i write...
I added constructors...
unfutunatly i can not post images... it says process returned 255, and here is an alert from windows that the program was not working corectly and it stoped working...
Here is all the code if someone have time and if it helps you to understand better..
#include <iostream>
using namespace std;
class Matrix{
double **val;
int rows,cols,errorCode;
public:
Matrix();
Matrix(int);
Matrix(int, int);
~Matrix();
void Print();
void Read();
double Get(int, int);
void Assign(int,int,double);
void Addition(Matrix&);
void Subtraction(Matrix&);
Matrix Multiply(Matrix&);
void Multiply(double);
};
Matrix::Matrix(){
//First array go with rows.
val = new double*[1];
val[0] = new double[1];
rows = 1;
cols = 1;
errorCode = 0;
}
Matrix::Matrix(int n){
rows = n;
cols = n;
val = new double*[rows];
for(int i = 0;i<rows;i++){
val[i] = new double[cols];
}
}
Matrix::Matrix(int n,int m){
rows = n;
cols = m;
val = new double*[rows];
for(int i = 0;i<rows;i++){
val[i] = new double[cols];
}
}
Matrix::~Matrix(){
for(int i=0;i<rows;i++){
delete[] val[i];
}
delete[] val;
}
void Matrix::Read(){
for(int i=0;i<rows;i++){
delete[] val[i];
}
delete[] val;
cout<<"Give the matrix dimensions (rows and cols) : ";
cin>>rows>>cols;
val = new double*[rows];
for(int i = 0;i<rows;i++){
val[i] = new double[cols];
}
cout<<"Give the matrix values: "<<endl;
for(int i = 0;i<rows;i++){
for(int j = 0;j<cols;j++){ cin>>val[i][j];}
}
}
void Matrix::Print(){
cout<<"The matrix with "<<rows<<" rows and "<<cols<<" cols, have next values: "<<endl;
for(int i = 0;i<rows;i++){
for(int j = 0;j<cols;j++){ cout<<val[i][j]<<" ";}
cout<<endl;
}
}
double Matrix::Get(int n, int m){
return val[n-1][m-1];
}
void Matrix::Assign(int n,int m,double v){
val[n-1][m-1] = v;
}
void Matrix::Addition(Matrix &a){
if(rows != a.rows || cols !=a.cols){
errorCode=111; //That means dimensions are not equal;
}
else{
for(int i = 0;i<rows;i++){
for(int j = 0;j<cols;j++){ val[i][j] += a.val[i][j];}
}
}
}
void Matrix::Subtraction(Matrix &a){
if(rows != a.rows || cols !=a.cols){
errorCode=111; //That means dimensions are not equal;
}
else{
for(int i = 0;i<rows;i++){
for(int j = 0;j<cols;j++){ val[i][j] -=a.val[i][j];}
}
}
}
void Matrix::Multiply(double x){
for(int i = 0;i<rows;i++){
for(int j = 0;j<cols;j++){ val[i][j] *= x;}
}
}
Matrix Matrix::Multiply(Matrix &a){
if(cols != a.rows){
errorCode=111; //That means dimensions are not equal;
Matrix b;
return b;
}
else{
Matrix b(rows,a.cols);
double p;
for(int i=0;i<rows;i++){
for(int j=0;j<a.cols;j++){
p=0;
for(int k=0;k<cols;k++){p += val[i][k]*a.val[k][j];}
b.Assign(i,j,p);
}
}
return b;
}
}
int main(){
Matrix a,b(2,3);
b.Assign(1,1,0);
b.Assign(1,2,3);
b.Assign(1,3,5);
b.Assign(2,1,5);
b.Assign(2,2,5);
b.Assign(2,3,2);
b.Print();
a.Read();
a.Print();
cout<<endl;
//when i read a i put 3x2 matrix, so the multiplying can be done.
Matrix c=a.Multiply(b);
c.Print();
return 0;
}
problem appear when i try to use function: Matrix Multiply(Matrix&).
There's an error in your default constructor:
val = new double*[1];
val[1] = new double[1];
1 is not a valid index for val, this should be:
val[0] = new double[1];
For an assignment we have been asked to create a program that can unshuffle a jumpled 512x512 gray scale image (it was shuffled by being broken down into 32x32 blocks). The greyscale image is imported into the project via text file and then it uses a predefined function to convert the values into a 1d array. Using this we were tasked with creating a matrix class that can store and ultimately manipulate the image with the intention of restoring the shuffled image.
I am having issues with creating submatrices to use in a comparison fashion (my general idea is selecting the first 32x32 block from the shuffled and the normal image then compare their pixel values to find a match). the function for my getBlock function is as follows:
Matrix Matrix::getBlock(int startRow, int endRow, int startColumn, int endColumn)
{
int Row = endRow - startRow;
int Column = endColumn - startColumn;
double* block = new double[(Row) *(Column)];
int n = endColumn - startColumn;
for (int ii = startRow; ii < endRow; ii++)
{
for (int jj = startColumn; jj < endColumn; jj++)
{
int k = ii*n + jj;
block[k] = data[ii*N + jj];
}
}
Matrix t(Row, Column, block);
return t;
delete[] block;
}
And in my main() i have attempted to implement the function as follows:
for (int x = 0; x < 480; x += 32) // so starts at 0 and continues if x less than 480 as 480 + 32 = 512
{
for (int y = 0; y < 480; y += 32) // same as x but with y
{
Matrix block = ShuffledCode.getBlock(x, (x + 32), y, (y + 32));
cout << block.sum() << endl;
}
}
My issue arises whenever the start column and the start row become anything other than 0, for instance in the above code the value is displayed for the first block (startrow 0, endrow 32, startcolumn 0, endcolumn 32) correctly however when the loop iterates i get a heap corruption error and i can't figure out what is going wrong. Another observation is that if i increase the endrow and endcolumn above 32 (so for instance if i increased them to 64) it seems to function fine and return the correct value.
If anyone has any ideas what could be causing it i would be very grateful, been working on it for days and haven't made any progress. I have also included all my code below in case the problem is related to another part of the program. the source.cpp file:
#include <sstream> // stringstream
#include <iostream> // cout, cerr
#include <fstream> // ifstream
#include <istream>
#include <assert.h>
#include "Matrix.H"
using namespace std;
// Input data are provided in .txt format and can be converted to .pgm files for visualization
// Download (free) ImageJ for plotting images in .pgm format
// http://rsb.info.nih.gov/ij/download.html
// Reads .txt file representing an image of R rows and C Columns stored in filename
// and converts it to a 1D array of doubles of size R*C
// Memory allocation is performed inside readTXT
double* readTXT(char *fileName, int sizeR, int sizeC);
// Converts a 1D array of doubles of size R*C to .pgm image of R rows and C Columns
// and stores .pgm in filename
// Use Q = 255 for greyscale images and Q=1 for binary images.
void WritePGM(char *filename, double *data, int sizeR, int sizeC, int Q);
int main()
{
// This part will show you how to use the two functions.
//M and N represent the number of rows and columns in the image,
//e.g. for task 1: logo_with_noise and logo_shuffled, M = 512, N = 512
//e.g. for task 2, Cluttered_scene, M = 768, N = 1024
//e.g. for task 2, Wally_grey, M = 49, N = 36
int M = 512; int N = 512; int count = 0;
// input_data is a pointer to a 1D array of M*N doubles stored in heap. Memory allocation is performed
// inside readTXT. readTXT will read an image (in .pgm format) of size MxN and will store the result in input_data.
// once you're done with data DO NOT forget to delete the memory as in the end of this main() function
double* input_data = 0;
double* noise_data = 0;
cout << endl;
cout << "Data from text file -------------------------------------------" << endl;
// shuffled image is stored in inputFileName, input_data holds the data in a 1d array
char* inputFileName = "C:\\Users\\Jamie\\SkyDrive\\Documents\\SoftwareDevAss\\ADS_Assignment\\Datafile\\logo_shuffled.txt";
input_data = readTXT(inputFileName, M, N);
// the img with noise is stored in inputFileName2, noise_data holds the data in a 1d array
char* inputFileName2 = "C:\\Users\\Jamie\\SkyDrive\\Documents\\SoftwareDevAss\\ADS_Assignment\\Datafile\\logo_with_noise.txt";
noise_data = readTXT(inputFileName2, M, N);
// this loop reduces the noise on the provided image to make it clear, uses threshold 170 as i found that gives the best results
for (int x = 0; x < 262144; x++)
{
if (noise_data[x] < 170)
{
noise_data[x] = 0;
}
else
{
noise_data[x] = 255;
}
}
/*long int pLength = 262144; // total length in pixels of 1d array holding the image
long int bLength = 1024; // total length in pixels of each block (32x32)
long int cLength = 262144; // current remaning length in pixels of 1d array holding the image
long int sum = 0; // theoretical limit of 262144 (if all pixels are white thus have the value 255)
for (int rBlocks = 0; rBlocks < 254; rBlocks++)
{
sum = 0;
cLength = pLength - ((rBlocks) * 1024);
double *sub = noise_data - cLength;
assert(sub[0] == noise_data[bLength * rBlocks]);
for (int i = 0; i < 1024; i++)
{
sum += sub[i];
}
cout << sum << endl;
}
*/
// at this point noise_data holds the original image.
Matrix ShuffledCode(512, 512, input_data);
Matrix SortedCode(512, 512, noise_data);
bool wedone = false;
int val = 1024;
// issue with increasing the start row and column above 0, end row and column can be increased fine.
for (int x = 0; x < 480; x += 32) // so starts at 0 and continues if x less than 480 as 480 + 32 = 512
{
for (int y = 0; y < 480; y += 32) // same as x but with y
{
Matrix block = ShuffledCode.getBlock(x, (x + 32), y, (y + 32));
cout << block.sum() << endl;
}
}
/*for (int x = 0; x < 262144; x++)
{
input_data[x] = noise_data[x];
}
*/
/*int MAX = 262144;
for (int i=0; i<MAX; i++)
{
for (int j = i + 1; j < MAX; j++)
{
if (input_data[i] == input_data[j] && noise_data[i] == noise_data[j])
{
}
else
{
input_data[i] = noise_data[i];
input_data[j] = noise_data[j];
}
}
}
*/
// writes data back to .pgm file stored in outputFileName
char* outputFileName = "C:\\Users\\Jamie\\SkyDrive\\Documents\\SoftwareDevAss\\ADS_Assignment\\Datafile\\logo_restored.pgm";
char* cleanFile = "C:\\Users\\Jamie\\SkyDrive\\Documents\\SoftwareDevAss\\ADS_Assignment\\Datafile\\logo_clean.pgm";
char* tester = "C:\\Users\\Jamie\\SkyDrive\\Documents\\SoftwareDevAss\\ADS_Assignment\\Datafile\\tester.pgm";
// Use Q = 255 for greyscale images and 1 for binary images.
int Q = 255;
WritePGM(outputFileName, input_data, M, N, Q);
WritePGM(cleanFile, noise_data, M, N, Q);
delete[] noise_data;
delete[] input_data;
return 0;
}
//Consructor
Matrix::Matrix(int sizeR, int sizeC, double* input_data)
{
M = sizeR;
N = sizeC;
data = new double[M*N];
for (int ii = 0; ii < M*N; ii++)
{
data[ii] = input_data[ii];
}
}
Matrix::Matrix(int sizeR, int sizeC)
{
M = sizeR;
N = sizeC;
data = new double[M*N];
for (int ii = 0; ii < M*N; ii++)
{
*(data + ii) = 0;
}
}
//Destructor
Matrix::~Matrix()
{
delete[] data;
}
//Copy Constructor
Matrix::Matrix(const Matrix& existingMatrix)
{
M = existingMatrix.getM();
N = existingMatrix.getN();
data = new double[M*N];
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
int k = ii*N + jj;
data[k] = existingMatrix.get(ii, jj);
}
}
}
//Pass by constant value
double Matrix::get(int i, int j) const
{
int k = i*N + j;
return data[k];
}
//Pass by Refrence
const void Matrix::set(int i, int j, double& val)
{
int k = i*N + j;
val = data[k];
}
//Return Value of M
int Matrix::getM() const
{
return M;
}
//Return Value of N
int Matrix::getN() const
{
return N;
}
//Returns part of the matrix
Matrix Matrix::getBlock(int startRow, int endRow, int startColumn, int endColumn)
{
int Row = endRow - startRow;
int Column = endColumn - startColumn;
double* block = new double[(Row) *(Column)];
int n = endColumn - startColumn;
for (int ii = startRow; ii < endRow; ii++)
{
for (int jj = startColumn; jj < endColumn; jj++)
{
int k = ii*n + jj;
block[k] = data[ii*N + jj];
}
}
Matrix t(Row, Column, block);
return t;
delete[] block;
}
//Allows for addion of Matricies, Operation Overloading.
Matrix Matrix::operator +(const Matrix& B)
{
Matrix C = Matrix(M, N, 0);
double temp;
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
temp = data[ii*N + jj] + B.get(ii, jj);
C.set(ii, jj, temp);
}
}
return C;
}
//Makes x and y equal, Opperation Overloading.
Matrix Matrix::operator =(const Matrix& B)
{
if (this == &B)
{
return *this;
}
else
{
M = B.getM();
N = B.getN();
delete[] data;
data = new double[M*N];
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
data[ii*N + jj] = B.get(ii, jj);
}
}
return *this;
}
}
//Allows for subtraction of matricies, Operation Overloading.
Matrix Matrix::operator -(const Matrix& B)
{
Matrix C = Matrix(M, N);
double temp;
for (int ii = 0; ii < M - 1; ii++)
{
for (int jj = 0; jj < N - 1; jj++)
{
temp = data[ii*N + jj] - B.get(ii, jj);
C.set(ii, jj, temp);
}
}
return C;
}
//Allows for multiplication of Matricies, Operation Overloading.
Matrix Matrix::operator *(const Matrix& B)
{
Matrix C = Matrix(M, B.getN());
double temp;
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
temp = data[ii*N + jj] * B.get(ii, jj);
C.set(ii, jj, temp);
}
}
return C;
}
//Allows for addition of Matricies, Operation Overloading.
Matrix Matrix::operator /(const Matrix& B)
{
Matrix C = Matrix(M, B.getN(), 0);
double temp;
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
temp = data[ii*N + jj] / B.get(ii, jj);
C.set(ii, jj, temp);
}
}
return C;
}
//Incrmentation of all values in Matrix by 1, Operation Overloading.
Matrix Matrix::operator ++()
{
for (int ii = 0; ii < M*N; ii++)
{
data[ii] = data[ii]++;
}
return *this;
}
//Allows calling of "get" function indirectly.
double Matrix::operator() (int i, int j)
{
return data[i*N + j];
}
double Matrix::sum()
{
double total = 0.0;
for (int ii = 0; ii < M*N; ii++)
{
total = total + data[ii];
}
return total;
}
void Matrix::out()
{
for (int ii = 0; ii < M*N; ii++)
{
if (data[ii] == 255)
cout << "1 ";
else
cout << data[ii] << " ";
}
}
// Read .txt file with image of size RxC, and convert to an array of doubles
double* readTXT(char *fileName, int sizeR, int sizeC)
{
double* data = new double[sizeR*sizeC];
int i = 0;
ifstream myfile(fileName);
if (myfile.is_open())
{
while (myfile.good())
{
if (i>sizeR*sizeC - 1) break;
myfile >> *(data + i);
// cout << *(data+i) << ' '; // This line display the converted data on the screen, you may comment it out.
i++;
}
myfile.close();
}
else cout << "Unable to open file";
//cout << i;
return data;
}
// convert data from double to .pgm stored in filename
void WritePGM(char *filename, double *data, int sizeR, int sizeC, int Q)
{
int i, j;
unsigned char *image;
ofstream myfile;
image = (unsigned char *) new unsigned char[sizeR*sizeC];
// convert the integer values to unsigned char
for (i = 0; i<sizeR*sizeC; i++)
image[i] = (unsigned char) data[i];
myfile.open(filename, ios::out | ios::binary | ios::trunc);
if (!myfile) {
cout << "Can't open file: " << filename << endl;
exit(1);
}
myfile << "P5" << endl;
myfile << sizeC << " " << sizeR << endl;
myfile << Q << endl;
myfile.write(reinterpret_cast<char *>(image), (sizeR*sizeC)*sizeof(unsigned char));
if (myfile.fail()) {
cout << "Can't write image " << filename << endl;
exit(0);
}
myfile.close();
delete[] image;
}
The Matrix class header file is as follows:
#pragma
#ifndef MATRIX_H
#define MATRIX_H
class Matrix
{
protected:
int M;
int N;
double* data;
public:
Matrix(int sizeR, int sizeC, double* input_data); //Constructor
Matrix(int sizeR, int sizeC);
~Matrix(); //Destructor
Matrix(const Matrix& existingMatrix); //Copy Constructor
double get(int i, int j) const; //Returns value at specified location
const void set(int i, int j, double& val);//Changes value at specified location
int getM() const; //Return value of M
int getN() const; //Return value of N
Matrix getBlock(int startRow, int endRow, int startColumn, int endColumn);//Return section of Matrix
Matrix operator + (const Matrix& B); // addition
Matrix operator = (const Matrix& B); // equals
Matrix operator - (const Matrix& B); // subtraction
Matrix operator * (const Matrix& B); // multiplication
Matrix operator / (const Matrix& B); // division
Matrix operator ++ (); // increment by 1
double operator () (int i, int j);
void out();
double sum();
};
class BinaryImage
:public Matrix
{
public:
BinaryImage(int sizeR, int sizeC, double* input_data, double thresh);
~BinaryImage();
BinaryImage(const Matrix& rhs, double thresh);
BinaryImage(const BinaryImage& existingBinIm);
const void set(int i, int j, double& val);
};
#endif
Any help would be much appreciated, thanks.
For starters, look at this in your getBlock method:
return t;
delete[] block;
The delete after the return means heap-memory is leaked since block never gets deleted.
Now why you have heap corruption:
You are always going to allocate a block that is 32*32 (see how you are calculating end - start? its always going to be 32)
// This is how you call, x = startRow, x+32 is endRow.
Matrix block = ShuffledCode.getBlock(x, (x + 32), y, (y + 32));
// This is inside your method: (endRow is startRow + 32) = 32 always
int Row = endRow - startRow;
But inside that method, you are accessing way beyond 32 using the input params. So when the loop gets to i = 1, startRow is 32 and end row is 64. But your matrix only goes to 32!