File: image.h

package info (click to toggle)
wsclean 2.10.1-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 2,596 kB
  • sloc: cpp: 41,625; ansic: 230; python: 174; makefile: 10
file content (184 lines) | stat: -rw-r--r-- 5,410 bytes parent folder | download
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#ifndef IMAGE_H
#define IMAGE_H

#include <cstring>
#include <cmath>
#include <complex>
#include <memory>

#include <aocommon/uvector.h>

template<typename NumT>
class ImageT
{
public:
	typedef NumT value_type;
	typedef value_type num_t;
	
	typedef value_type* iterator;
	typedef const value_type* const_iterator;
	
	typedef std::unique_ptr<ImageT<NumT>> Ptr;
	
	ImageT() : _data(nullptr), _width(0), _height(0) { }
	ImageT(size_t width, size_t height);
	ImageT(size_t width, size_t height, value_type initialValue);
	
	~ImageT();
	
	ImageT(const ImageT<NumT>&);
	ImageT<NumT>& operator=(const ImageT<NumT>&);
	ImageT<NumT>& operator=(value_type value);
	
	ImageT(ImageT<NumT>&& source);
	ImageT<NumT>& operator=(ImageT<NumT>&& source);
	
	static Ptr Make(size_t width, size_t height) { 
		return Ptr(new ImageT<NumT>(width, height));
	}
	static Ptr Make(size_t width, size_t height, value_type initialValue) { 
		return Ptr(new ImageT<NumT>(width, height, initialValue));
	}
	
	value_type* data() { return _data; }
	const value_type* data() const { return _data; }
	
	size_t Width() const { return _width; }
	size_t Height() const { return _height; }
	size_t size() const { return _width * _height; }
	bool empty() const { return _width == 0 || _height == 0; }
	
	iterator begin() { return _data; }
	const_iterator begin() const { return _data; }
	
	iterator end() { return _data + _width*_height; }
	const_iterator end() const { return _data + _width*_height; }
	
	const value_type& operator[](size_t index) const { return _data[index]; }
	value_type& operator[](size_t index) { return _data[index]; }
	
	ImageT<NumT>& operator+=(const ImageT<NumT>& other);
	ImageT<NumT>& operator-=(const ImageT<NumT>& other);
	
	ImageT<NumT>& operator*=(value_type factor);
	ImageT<NumT>& operator*=(const ImageT<NumT>& other);
	
	void reset();
	
	/** Cut-off the borders of an image.
	 * @param outWidth Should be &lt;= inWidth.
	 * @param outHeight Should be &lt;= inHeight.
	 */
	static void Trim(value_type* output, size_t outWidth, size_t outHeight, const value_type* input, size_t inWidth, size_t inHeight);
	
	ImageT<NumT> Trim(size_t outWidth, size_t outHeight) const
	{
		ImageT<NumT> image(outWidth, outHeight);
		Trim(image.data(), outWidth, outHeight, data(), Width(), Height());
		return image;
	}
	
	ImageT<NumT> TrimBox(size_t x1, size_t y1, size_t boxWidth, size_t boxHeight) const
	{
		ImageT<NumT> image(boxWidth, boxHeight);
		TrimBox(image.data(), x1, y1, boxWidth, boxHeight, data(), Width(), Height());
		return image;
	}
	
	template<typename T>
	static void TrimBox(T* output, size_t x1, size_t y1, size_t boxWidth, size_t boxHeight, const T* input, size_t inWidth, size_t inHeight);
	
	template<typename T>
	static void CopyMasked(T* to, size_t toX, size_t toY, size_t toWidth, const T* from, size_t fromWidth, size_t fromHeight, const bool* fromMask);
	
	/** Extend an image with zeros, complement of Trim.
	 * @param outWidth Should be &gt;= inWidth.
	 * @param outHeight Should be &gt;= inHeight.
	 */
	static void Untrim(value_type* output, size_t outWidth, size_t outHeight, const value_type* input, size_t inWidth, size_t inHeight);
	
	ImageT<NumT> Untrim(size_t outWidth, size_t outHeight) const
	{
		ImageT<NumT> image(outWidth, outHeight);
		Untrim(image.data(), outWidth, outHeight, data(), Width(), Height());
		return image;
	}
	
	static value_type Median(const value_type* data, size_t size)
	{
		aocommon::UVector<value_type> copy;
		return median_with_copy(data, size, copy);
	}
	
	static value_type MAD(const value_type* data, size_t size);
	
	value_type Sum() const;
	value_type Average() const;
	
	value_type Min() const;
	value_type Max() const;
	
	value_type StdDevFromMAD() const { return StdDevFromMAD(_data, _width*_height); }
	static value_type StdDevFromMAD(const value_type* data, size_t size)
	{
		// norminv(0.75) x MAD
		return value_type(1.48260221850560) * MAD(data, size);
	}
	
	value_type RMS() const { return RMS(_data, _width*_height); }
	static value_type RMS(const value_type* data, size_t size)
	{
		value_type sum = 0.0;
		for(size_t i=0; i!=size; ++i)
			sum += data[i]*data[i];
		return std::sqrt(sum/value_type(size));
	}
	
	void Negate()
	{
		for(value_type& d : *this)
			d = -d;
	}
	
	void Serialize(class SerialOStream& stream) const;
	void Unserialize(class SerialIStream& stream);
private:
	value_type* _data;
	size_t _width, _height;
	
	static value_type median_with_copy(const value_type* data, size_t size, aocommon::UVector<value_type>& copy);
};

template<typename NumT>
template<typename T>
void ImageT<NumT>::TrimBox(T* output, size_t x1, size_t y1, size_t boxWidth, size_t boxHeight, const T* input, size_t inWidth, size_t /*inHeight*/)
{
	size_t endY = y1 + boxHeight;
	for(size_t y=y1; y!=endY; ++y)
	{
		std::copy_n(&input[y*inWidth + x1], boxWidth, &output[(y-y1)*boxWidth]);
	}
}

template<typename NumT>
template<typename T>
void ImageT<NumT>::CopyMasked(T* to, size_t toX, size_t toY, size_t toWidth, const T* from, size_t fromWidth, size_t fromHeight, const bool* fromMask)
{
	for(size_t y=0; y!=fromHeight; ++y)
	{
		for(size_t x=0; x!=fromWidth; ++x)
		{
			if(fromMask[y*fromWidth + x])
				to[toX + (toY+y) * toWidth + x] = from[y*fromWidth + x];
		}
	}
}

typedef ImageT<double> Image;
typedef ImageT<float> ImageF;
typedef ImageT<std::complex<float>> ImageCF;

template<class T>
using ImageTC = ImageT<std::complex<T>>;

#endif