-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathImage.cpp
More file actions
171 lines (147 loc) · 5.4 KB
/
Image.cpp
File metadata and controls
171 lines (147 loc) · 5.4 KB
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
158
159
160
161
162
163
164
165
166
167
168
169
170
///////////////////////////////////////////////////////////////////////////
//
// NAME
// Image.cpp -- a simple reference-counted image structure
//
// SEE ALSO
// Image.h definition and explanation of these classes
//
// Copyright © Richard Szeliski, 2001.
// See Copyright.h for more details
//
///////////////////////////////////////////////////////////////////////////
#include "Image.h"
#include "Error.h"
//
// struct CShape: shape of image (width x height x nbands)
//
bool CShape::operator==(const CShape& ref)
{
// Are two shapes the same?
return (width == ref.width &&
height == ref.height &&
nBands == ref.nBands);
}
bool CShape::SameIgnoringNBands(const CShape& ref)
{
// Are two shapes the same ignoring the number of bands?
return (width == ref.width &&
height == ref.height);
}
bool CShape::operator!=(const CShape& ref)
{
// Are two shapes not the same?
return ! ((*this) == ref);
}
//
// class CImage : generic (weakly typed) image
//
void CImage::SetDefaults()
{
// Set internal state to default values
m_pTI = 0; // pointer to type_info class
m_bandSize = 0; // size of each band in bytes
m_pixSize = 0; // stride between pixels in bytes
m_rowSize = 0; // stride between rows in bytes
m_memStart = 0; // start of addressable memory
alphaChannel = 3; // which channel contains alpha (for compositing)
// Set default attribute values
alphaChannel = 3; // which channel contains alpha (for compositing)
origin[0] = 0; // x and y coordinate origin (for some operations)
origin[1] = 0; // x and y coordinate origin (for some operations)
borderMode = eBorderReplicate; // border behavior for neighborhood operations...
}
CImage::CImage()
{
// Default constructor
SetDefaults();
}
CImage::CImage(CShape s, const type_info& ti, int cS)
{
SetDefaults();
ReAllocate(s, ti, cS, 0, true, 0);
}
void CImage::ReAllocate(CShape s, const type_info& ti, int bandSize,
bool evenIfSameShape)
{
if (! evenIfSameShape && s == m_shape && ti == *m_pTI && bandSize == m_bandSize)
return;
ReAllocate(s, ti, bandSize, 0, true, 0);
}
void CImage::ReAllocate(CShape s, const type_info& ti, int bandSize,
void *memory, bool deleteWhenDone, int rowSize)
{
// Set up the type_id, shape, and size info
m_shape = s; // image shape (dimensions)
m_pTI = &ti; // pointer to type_info class
m_bandSize = bandSize; // size of each band in bytes
m_pixSize = m_bandSize * s.nBands; // stride between pixels in bytes
// Do the real allocation work
m_rowSize = (rowSize) ? rowSize : // stride between rows in bytes
(m_pixSize * s.width + 7) & -8; // round up to 8 (quadwords)
int nBytes = m_rowSize * s.height;
if (memory == 0 && nBytes > 0) // allocate if necessary
{
memory = new double[(nBytes + 7)/ 8];
if (memory == 0)
throw CError("CImage::Reallocate: could not allocate %d bytes", nBytes);
}
m_memStart = (char *) memory; // start of addressable memory
m_memory.ReAllocate(nBytes, memory, deleteWhenDone);
}
void CImage::DeAllocate()
{
// Release the memory & set to default values
ReAllocate(CShape(), *(const type_info *) 0, 0, 0, false, 0);
SetDefaults();
}
void CImage::SetSubImage(int x, int y, int width, int height)
{
// Adjust the start of memory pointer
m_memStart = (char *) PixelAddress(x, y, 0);
// Compute area of intersection and adjust the shape and origin
int x1 = __min(m_shape.width, x+width); // end column
int y1 = __min(m_shape.height, y+height); // end row
x = __max(0, __min(x, m_shape.width)); // clip to original shape
y = __max(0, __min(y, m_shape.height)); // clip to original shape
m_shape.width = x1 - x; // actual width
m_shape.height = y1 - y; // actual height
}
void CImage::SetPixels(void *val_ptr)
{
// Fill the image with a value
uchar *vc = (uchar *) val_ptr;
// Test if all the bytes are the same
bool all_same = true;
for (int b = 0; b < m_bandSize; b++)
all_same = all_same && (vc[b] == vc[0]);
// Iterate over the rows
int nC = m_shape.width * m_shape.nBands;
for (int y = 0; y < m_shape.height; y++)
{
uchar *rp = (uchar *) PixelAddress(0, y, 0);
if (all_same)
memset(rp, vc[0], nC * m_bandSize);
else if (m_bandSize == sizeof(int))
{
int vi = *(int *) val_ptr;
int *ip = (int *) rp;
for (int c = 0; c < nC; c++)
ip[c] = vi;
}
else
{
for (int c = 0; c < nC; c++, rp += m_bandSize)
memcpy(rp, vc, m_bandSize);
}
}
}
//
// class CImageOf<T>: strongly typed image
//
template <> uchar CImageOf<uchar>::MinVal(void) { return 0; }
template <> uchar CImageOf<uchar>::MaxVal(void) { return 255; }
template <> int CImageOf<int >::MinVal(void) { return 0x80000000; }
template <> int CImageOf<int >::MaxVal(void) { return 0x7fffffff; }
template <> float CImageOf<float>::MinVal(void) { return -FLT_MAX; }
template <> float CImageOf<float>::MaxVal(void) { return FLT_MAX; }