-
Notifications
You must be signed in to change notification settings - Fork 0
/
Image.cpp
133 lines (99 loc) · 2.4 KB
/
Image.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
#include <cmath>
#include <limits>
#include <fstream>
#include "Image.hpp"
Image::Image(std::string filename)
{
std::ifstream stream(filename.c_str());
if ( ! stream.is_open() )
throw ImageException("Cannot open file for reading");
init(stream);
}
Image::Image(std::istream& stream)
{
init(stream);
}
Image::Image(int width, int height)
{
if ((m_width = width ) < 0)
throw ImageException("Image width is < 0");
if ((m_height = height) < 0)
throw ImageException("Image height is < 0");
m_data = new float[ area() ];
for (int i = 0; i < area(); i++)
m_data[i] = 0;
}
Image::Image(const Image& other)
{
m_width = other.m_width ;
m_height = other.m_height;
m_data = new float[ area() ];
for (int i = 0; i < area(); i++)
m_data[i] = other.m_data[i];
}
Image::~Image()
{
delete[] m_data;
}
float &
Image::operator() (int row, int col)
{
if (row >= m_height || row < 0)
throw ImageException("Requested pixel row out of bounds");
if (col >= m_width || col < 0)
throw ImageException("Requested pixel column out of bounds");
return m_data[m_width * row + col];
}
float
Image::operator() (int row, int col) const
{
if (row >= m_height || row < 0)
return 0;
if (col >= m_width || col < 0)
return 0;
return m_data[m_width * row + col];
}
void
Image::normalize()
{
float vMin = std::numeric_limits<float>::infinity();
float vMax = -vMin;
for (int i = 0; i < area(); i++)
{
vMin = std::min(vMin, m_data[i]);
vMax = std::max(vMax, m_data[i]);
}
float width = vMax - vMin;
for (int i = 0; i < area(); i++)
m_data[i] = (width) ? (m_data[i] - vMin) / width : 0;
}
void
Image::save(std::string filename, float maxVal, int depth) const
{
std::ofstream stream(filename.c_str());
if ( ! stream.is_open() )
throw ImageException("Cannot open file for writing");
stream << "P2" << std::endl;
stream << m_width << " " << m_height << std::endl;
stream << depth << std::endl;
for (int i = 0; i < area(); i++)
stream << (int) std::floor(depth * m_data[i] / maxVal) << std::endl;
}
void
Image::init(std::istream& stream)
{
if (stream.get() != 'P')
throw ImageException("File does not appear to be PGM");
if (stream.get() != '2')
throw ImageException("Only grayscale (P2) files supported");
stream >> m_width >> m_height;
m_data = new float[ area() ];
float val;
int maxVal;
stream >> maxVal;
for (int i = 0; i < area(); i++)
{
stream >> val;
m_data[i] = val / maxVal;
}
}