-
Notifications
You must be signed in to change notification settings - Fork 0
/
Filehandler.cpp
157 lines (134 loc) · 4.83 KB
/
Filehandler.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <iostream>
#include <fstream>
#include <istream>
#include "FileHandler.h"
#include "Shared.h"
/*
* Default constructor. Used to create a FileHandler for writing only.
*/
FileHandler::FileHandler(){
#ifdef VERBOSE
std::cout << "You have created a filehandler without a in file.. You cannot use the read functions" << std::endl;
#endif
FileHandler::filename = NULL;
}
/*
* Created a filehandler to read and write to a file.
* @param filename a pointer to a character array for the filename
*/
FileHandler::FileHandler(char *filename)
{
FileHandler::filename = filename;
}
/*
* Destructor. This doesn't have to do anything as I'm not assigning memory
* or anything like that in the constructor.
*/
FileHandler::~FileHandler()
{
#ifdef VERBOSE
if (!FileHandler::filename){
std::cout << "A filehandler for a file without a name has been destroyed" << std::endl;
return;
}
std::cout << "File handler for \"" << FileHandler::filename << "\" has been destroyed" << std::endl;
#endif
}
/*
* Reads image data from the file and returns a pointer to a array
* that contains the file's data.
* @param rows The number of rows in the image (height in pixels)
* @param cols The number of columns in the image (width in pixels)
* @return A array that contains the pixel data for the inage
*/
double * FileHandler::readFile(int rows, int cols)
{
if( FileHandler::filename == false ){ // If it's a write-only filehandler
std::cout << "I don't have a file to read.. " << std::endl;
throw 1; // Just throw an error... Break everything!!
}
double * data = new double[cols*rows]; // Array of data we've read in
int i = 0;
std::ifstream _file(FileHandler::filename); // Open this file for reading
if (_file.is_open()) { // Make sure it's open
while (_file.good()) { // While there's no erors
if (i > ((rows * cols) - 1)) break; // If we're at the end of the image data
_file >> *(data + i); // Read the current pixel value into the array
#ifdef VERBOSE
std::cout << (char)*(data + i);
#endif
i++;
}
std::cout << "I've read all the data from \"" << FileHandler::filename << "\".\n";
_file.close(); // Make sure the file is closed
}
else { // We couldn't open the file :(
std::cerr << "Couldn't open file with the name \"" << FileHandler::filename << "\".\nPlease make sure it's in the same directory as the program." << std::endl;
throw 1;
}
return data; // Return the array of data
}
/*
* Reads the image data from the file and turns it into a Matrix.
* @param rows The number of rows in the image (height in pixels)
* @param cols The number of columns in the image (width in pixels)
* @return A matrix containing the pixel values for the image
*/
Matrix * FileHandler::readImage(int rows, int cols) {
Matrix * matrix = new Matrix(rows, cols); // Our image matrix
int i = 0;
try {
double * data = readFile(rows, cols); // Get the array of pixel values
#ifdef VERBOSE
std::cout << "\nData before convertion: " << *data << std::endl;
#endif
matrix->convertArray(data); // Put the pixel data into the matrix
//Data should be deleted when the convertArray function has finished.
return matrix;
}
catch (int e) { // Make sure we catch any errors (file not opening etc)
throw e;
}
}
/*
* Writes a given matrix to the file supplied in PGM format.
* @param outputfile A pointer to a character array for the output filename.
* @param matrix A pointer to the Matrix to write
* @param Q What type of image is it (255=Greyscale, 0=Binary)
*/
void FileHandler::writeMatrix(char * outputFile, Matrix * matrix, int Q) {
int rows = matrix->getRows(); // How heigh is the image
int cols = matrix->getCols(); // How wide is the image
unsigned char * imageData = (unsigned char *) new unsigned char[rows * cols];
//Convert the matrix to a array
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
imageData[i * cols + j] = (unsigned char)matrix->getAt(i, j);
}
}
std::ofstream _file;
// Open the file for writing, in binary, overriding any existing file.
_file.open(outputFile, std::ios::out | std::ios::binary | std::ios::trunc);
if (!_file) {
std::cout << "Cann't open file \"" << outputFile << "\" for writing." << std::endl;
throw 1;
}
#ifdef VERBOSE
std::cout << "Writing headers" << std::endl;
#endif
// Magical header for PGM files.
_file << "P5" << std::endl;
_file << cols << " " << rows << std::endl;
_file << Q << std::endl;
// Write the image data
_file.write(reinterpret_cast<char *>(imageData), (rows*cols) * sizeof(unsigned char));
#ifdef VERBOSE
std::cout << "Written image data." << std::endl;
#endif
if (_file.fail()) {// If we didn't write :(
std::cout << "Couldn't write image data to file \"" << outputFile << "\"\n";
throw 1;
}
_file.close(); // Close that file!
delete[] imageData; // Delete the imageData.. It's been saved anyways
}