Blame view

stim/image/image.h 12.1 KB
d32a1854   David Mayerich   added framework f...
1
2
  #ifndef STIM_IMAGE_H
  #define STIM_IMAGE_H
fbf0ab02   David Mayerich   added support for...
3
  
c8c976a9   David Mayerich   replaced CImg wit...
4
5
  #include <opencv2/core/core.hpp>
  #include <opencv2/highgui/highgui.hpp>
912d9073   David Mayerich   added vector.h to...
6
  #include <vector>
d32a1854   David Mayerich   added framework f...
7
  #include <iostream>
a2bf1d08   David Mayerich   general bug fixes...
8
  #include <limits>
0bb6cf51   David Mayerich   fixed image for c...
9
  #include <typeinfo>
6d30a707   Tianshu Cheng   add cuda/array_ad...
10
  
7b3948ab   David Mayerich   added support for...
11
  namespace stim{
c8c976a9   David Mayerich   replaced CImg wit...
12
13
  /// This static class provides the STIM interface for loading, saving, and storing 2D images.
  /// Data is stored in an interleaved (BIP) format (default for saving and loading is RGB).
d32a1854   David Mayerich   added framework f...
14
15
16
17
18
19
  
  //currently this interface uses CImg
  //	T = data type (usually unsigned char)
  template <class T>
  class image{
  
c8c976a9   David Mayerich   replaced CImg wit...
20
21
22
23
  	//cimg_library::CImg<T> img;
  	T* img;										//pointer to the image data (assumes RGB for loading/saving)
  	size_t R[3];
  
a2bf1d08   David Mayerich   general bug fixes...
24
25
26
  	size_t X() const { return R[1]; }
  	size_t Y() const { return R[2]; }
  	size_t C() const { return R[0]; }
c8c976a9   David Mayerich   replaced CImg wit...
27
  
e9a1b974   Pavel Govyadinov   imlemented Dr. Ma...
28
29
  	size_t bytes(){ return size() * sizeof(T); }
  
c8c976a9   David Mayerich   replaced CImg wit...
30
31
32
33
34
35
36
  	void init(){								//initializes all variables, assumes no memory is allocated
  		memset(R, 0, sizeof(size_t) * 3);		//set the resolution and number of channels to zero
  		img = NULL;
  	}
  
  	void unalloc(){								//frees any resources associated with the image
  		if(img)	free(img);						//if memory has been allocated, free it
735a2a24   David Mayerich   started testing o...
37
  		img=NULL;		
c8c976a9   David Mayerich   replaced CImg wit...
38
  	}
1a224b6a   David Mayerich   fixed linux compa...
39
  
c8c976a9   David Mayerich   replaced CImg wit...
40
41
42
43
44
45
46
  
  	void clear(){								//clears all image data
  		unalloc();								//unallocate previous memory
  		init();									//re-initialize the variables
  	}
  
  	void allocate(){
e9a1b974   Pavel Govyadinov   imlemented Dr. Ma...
47
48
49
  		unalloc();
  		img = (T*) malloc( bytes() );	//allocate memory
  		memset(img, 0, bytes());
c8c976a9   David Mayerich   replaced CImg wit...
50
51
52
  	}
  
  	void allocate(size_t x, size_t y, size_t c){	//allocate memory based on the resolution
e9a1b974   Pavel Govyadinov   imlemented Dr. Ma...
53
  		unalloc();
c8c976a9   David Mayerich   replaced CImg wit...
54
55
56
57
  		R[0] = c; R[1] = x; R[2] = y;				//set the resolution
  		allocate();									//allocate memory
  	}
  
c8c976a9   David Mayerich   replaced CImg wit...
58
59
60
61
  
  	size_t idx(size_t x, size_t y, size_t c = 0){
  		return y * C() * X() + x * C() + c;
  	}
1a224b6a   David Mayerich   fixed linux compa...
62
  
c8c976a9   David Mayerich   replaced CImg wit...
63
64
  
  	int cv_type(){
3ff136b3   David Mayerich   replaced C++11 co...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  		// The following is C++ 11 code, but causes problems on some compilers (ex. nvcc). Below is my best approximation to a solution
  
  		//if(std::is_same<T, unsigned char>::value)	return CV_MAKETYPE(CV_8U, (int)C());
  		//if(std::is_same<T, char>::value)			return CV_MAKETYPE(CV_8S, (int)C());
  		//if(std::is_same<T, unsigned short>::value)	return CV_MAKETYPE(CV_16U, (int)C());
  		//if(std::is_same<T, short>::value)			return CV_MAKETYPE(CV_16S, (int)C());
  		//if(std::is_same<T, int>::value)				return CV_MAKETYPE(CV_32S, (int)C());
  		//if(std::is_same<T, float>::value)			return CV_MAKETYPE(CV_32F, (int)C());
  		//if(std::is_same<T, double>::value)			return CV_MAKETYPE(CV_64F, (int)C());
  
  		if(typeid(T) == typeid(unsigned char))		return CV_MAKETYPE(CV_8U, (int)C());
  		if(typeid(T) == typeid(char))				return CV_MAKETYPE(CV_8S, (int)C());
  		if(typeid(T) == typeid(unsigned short))		return CV_MAKETYPE(CV_16U, (int)C());
  		if(typeid(T) == typeid(short))				return CV_MAKETYPE(CV_16S, (int)C());
  		if(typeid(T) == typeid(int))				return CV_MAKETYPE(CV_32S, (int)C());
  		if(typeid(T) == typeid(float))				return CV_MAKETYPE(CV_32F, (int)C());
  		if(typeid(T) == typeid(double))				return CV_MAKETYPE(CV_64F, (int)C());
1a224b6a   David Mayerich   fixed linux compa...
82
  
c8c976a9   David Mayerich   replaced CImg wit...
83
  		std::cout<<"ERROR in stim::image::cv_type - no valid data type found"<<std::endl;
3ff136b3   David Mayerich   replaced C++11 co...
84
  		exit(1);
c8c976a9   David Mayerich   replaced CImg wit...
85
86
  	}
  
a2bf1d08   David Mayerich   general bug fixes...
87
88
  	/// Returns the value for "white" based on the dynamic range (assumes white is 1.0 for floating point images)
  	T white(){
3ff136b3   David Mayerich   replaced C++11 co...
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  		// The following is C++ 11 code, but causes problems on some compilers (ex. nvcc). Below is my best approximation to a solution
  
  		//if(std::is_same<T, unsigned char>::value)		return UCHAR_MAX;
  		//if(std::is_same<T, unsigned short>::value)		return SHRT_MAX;
  		//if(std::is_same<T, unsigned>::value)			return UINT_MAX;
  		//if(std::is_same<T, unsigned long>::value)		return ULONG_MAX;
  		//if(std::is_same<T, unsigned long long>::value)	return ULLONG_MAX;
  		//if(std::is_same<T, float>::value)				return 1.0f;
  		//if(std::is_same<T, double>::value)				return 1.0;
  
  		if(typeid(T) == typeid(unsigned char))		return UCHAR_MAX;
  		if(typeid(T) == typeid(unsigned short))		return SHRT_MAX;
  		if(typeid(T) == typeid(unsigned))			return UINT_MAX;
  		if(typeid(T) == typeid(unsigned long))		return ULONG_MAX;
  		if(typeid(T) == typeid(unsigned long long))	return ULLONG_MAX;
  		if(typeid(T) == typeid(float))				return 1.0f;
  		if(typeid(T) == typeid(double))				return 1.0;
a2bf1d08   David Mayerich   general bug fixes...
106
107
  
  		std::cout<<"ERROR in stim::image::white - no white value known for this data type"<<std::endl;
3ff136b3   David Mayerich   replaced C++11 co...
108
  		exit(1);
a2bf1d08   David Mayerich   general bug fixes...
109
110
  	}
  
d32a1854   David Mayerich   added framework f...
111
112
113
  
  public:
  
a2bf1d08   David Mayerich   general bug fixes...
114
  	/// Default constructor - creates an empty image object
735a2a24   David Mayerich   started testing o...
115
116
117
  	image(){
  		init();						//initialize all variables to zero, don't allocate any memory
  	}							
7b3948ab   David Mayerich   added support for...
118
  
a2bf1d08   David Mayerich   general bug fixes...
119
  	/// Constructor with a filename - loads the specified file
c8c976a9   David Mayerich   replaced CImg wit...
120
  	image(std::string filename){				//constructor initialize the image with an image file
fba6e7e3   Pavel Govyadinov   fixed image.h bug...
121
  		init();
c8c976a9   David Mayerich   replaced CImg wit...
122
  		load(filename);
7b3948ab   David Mayerich   added support for...
123
124
  	}
  
c8c976a9   David Mayerich   replaced CImg wit...
125
  	/// Create a new image from scratch given a number of samples and channels
1a224b6a   David Mayerich   fixed linux compa...
126
  	image(size_t x, size_t y = 1, size_t c = 1){
e9a1b974   Pavel Govyadinov   imlemented Dr. Ma...
127
  		init();
a2bf1d08   David Mayerich   general bug fixes...
128
  		allocate(x, y, c);
c8c976a9   David Mayerich   replaced CImg wit...
129
  	}
f186dbda   Tianshu Cheng   header file for b...
130
  
a2bf1d08   David Mayerich   general bug fixes...
131
  	/// Create a new image with the data given in 'data'
c8c976a9   David Mayerich   replaced CImg wit...
132
  	image(T* data, size_t x, size_t y, size_t c = 1){
e9a1b974   Pavel Govyadinov   imlemented Dr. Ma...
133
  		init();
c8c976a9   David Mayerich   replaced CImg wit...
134
135
  		allocate(x, y, c);
  		memcpy(img, data, bytes());
41acaf5d   David Mayerich   added a CUDA Gaus...
136
137
  	}
  
a2bf1d08   David Mayerich   general bug fixes...
138
  	/// Copy constructor - duplicates an image object
735a2a24   David Mayerich   started testing o...
139
  	image(const stim::image<T> &I){
e9a1b974   Pavel Govyadinov   imlemented Dr. Ma...
140
  		init();
a2bf1d08   David Mayerich   general bug fixes...
141
  		allocate(I.X(), I.Y(), I.C());
a2bf1d08   David Mayerich   general bug fixes...
142
143
144
145
146
147
148
149
  		memcpy(img, I.img, bytes());
  	}
  
  	/// Destructor - clear memory
  	~image(){
  		free(img);
  	}
  
735a2a24   David Mayerich   started testing o...
150
  	stim::image<T>& operator=(const stim::image<T>& I){
a2bf1d08   David Mayerich   general bug fixes...
151
152
153
154
155
156
157
  		if(&I == this)									//handle self-assignment
  			return *this;
  		allocate(I.X(), I.Y(), I.C());
  		memcpy(img, I.img, bytes());
  		return *this;
  	}
  
c8c976a9   David Mayerich   replaced CImg wit...
158
  	/// Load an image from a file
d32a1854   David Mayerich   added framework f...
159
  	void load(std::string filename){
c8c976a9   David Mayerich   replaced CImg wit...
160
161
  
  		cv::Mat cvImage = cv::imread(filename, CV_LOAD_IMAGE_UNCHANGED);	//use OpenCV to open the image file
a2bf1d08   David Mayerich   general bug fixes...
162
  		if(!cvImage.data){
735a2a24   David Mayerich   started testing o...
163
  			std::cout<<"ERROR stim::image::load() - unable to find image "<<filename<<" ["<<__FILE__<<" (line "<<__LINE__<<")]"<<std::endl;
a2bf1d08   David Mayerich   general bug fixes...
164
165
  			exit(1);
  		}
c8c976a9   David Mayerich   replaced CImg wit...
166
  		allocate(cvImage.cols, cvImage.rows, cvImage.channels());			//allocate space for the image
ae05c3e4   Pavel Govyadinov   Found an error wi...
167
168
169
170
  		T* cv_ptr = (T*) cvImage.data;
  		if(C() == 1)
  		{
  	//if this is a single-color image, just copy the data
ae05c3e4   Pavel Govyadinov   Found an error wi...
171
  			memcpy(img, cv_ptr, bytes());     
ae05c3e4   Pavel Govyadinov   Found an error wi...
172
  		}
e9a1b974   Pavel Govyadinov   imlemented Dr. Ma...
173
174
  		if(C() == 3)
  		{														//if this is a 3-color image, OpenCV uses BGR interleaving
a2bf1d08   David Mayerich   general bug fixes...
175
  			set_interleaved_bgr(cv_ptr, X(), Y());
e9a1b974   Pavel Govyadinov   imlemented Dr. Ma...
176
  		}
ae05c3e4   Pavel Govyadinov   Found an error wi...
177
  
e9a1b974   Pavel Govyadinov   imlemented Dr. Ma...
178
  		cvImage.release();	
d32a1854   David Mayerich   added framework f...
179
180
181
182
  	}
  
  	//save a file
  	void save(std::string filename){
c8c976a9   David Mayerich   replaced CImg wit...
183
184
  		//OpenCV uses an interleaved format, so convert first and then output
  		T* buffer = (T*) malloc(bytes());
a2bf1d08   David Mayerich   general bug fixes...
185
186
187
188
  
  		if(C() == 1)
  			memcpy(buffer, img, bytes());
  		else if(C() == 3)
9b766f1f   Pavel Govyadinov   completed merge f...
189
  			get_interleaved_bgr(buffer);
c8c976a9   David Mayerich   replaced CImg wit...
190
191
  		cv::Mat cvImage((int)Y(), (int)X(), cv_type(), buffer);
  		cv::imwrite(filename, cvImage);
ae05c3e4   Pavel Govyadinov   Found an error wi...
192
193
  		cvImage.release();
  		free(buffer);
d32a1854   David Mayerich   added framework f...
194
195
  	}
  
8b7be670   David Mayerich   implemented savin...
196
  	//create an image from an interleaved buffer
ae05c3e4   Pavel Govyadinov   Found an error wi...
197
198
  	void set_interleaved_rgb(T* buffer, size_t width, size_t height, size_t channels = 3){
  		allocate(width, height, channels);
c8c976a9   David Mayerich   replaced CImg wit...
199
200
  		memcpy(img, buffer, bytes());
  	}
fbf0ab02   David Mayerich   added support for...
201
  
ae05c3e4   Pavel Govyadinov   Found an error wi...
202
203
  	void set_interleaved_bgr(T* buffer, size_t width, size_t height, size_t channels = 3){
  		allocate(width, height, channels);
c8c976a9   David Mayerich   replaced CImg wit...
204
205
206
207
208
  		for(size_t c = 0; c < C(); c++){								//copy directly
  			for(size_t y = 0; y < Y(); y++){
  				for(size_t x = 0; x < X(); x++){
  					img[idx(x, y, c)] = buffer[y * X() * C() + x * C() + (2-c)];
  				}
fbf0ab02   David Mayerich   added support for...
209
210
  			}
  		}
8b7be670   David Mayerich   implemented savin...
211
212
  	}
  
9b766f1f   Pavel Govyadinov   completed merge f...
213
  	void get_interleaved_bgr(T* data){
8b7be670   David Mayerich   implemented savin...
214
215
  
  		//for each channel
c8c976a9   David Mayerich   replaced CImg wit...
216
217
218
219
220
221
222
  		for(size_t y = 0; y < Y(); y++){
  			for(size_t x = 0; x < X(); x++){
  				for(size_t c = 0; c < C(); c++){
  					data[y * X() * C() + x * C() + (2-c)] = img[idx(x, y, c)];
  				}
  			}
  		}
8b7be670   David Mayerich   implemented savin...
223
224
  	}
  
9b766f1f   Pavel Govyadinov   completed merge f...
225
226
227
228
  	void get_interleaved_rgb(T* data){
  		memcpy(data, img, bytes());
  	}
  
904614c3   David Mayerich   added normalizati...
229
230
231
232
233
234
235
236
237
238
239
240
  	//copies data in the given channel order as a non-interleaved image
  	void get_noninterleaved(T* data){
  		//for each channel
  		for(size_t y = 0; y < Y(); y++){
  			for(size_t x = 0; x < X(); x++){
  				for(size_t c = 0; c < C(); c++){
  					data[c * Y() * X() + y * X() + x] = img[idx(x, y, c)];
  				}
  			}
  		}
  	}
  
9b766f1f   Pavel Govyadinov   completed merge f...
241
  
9d3ba0b1   David Mayerich   added stim::hsi a...
242
  	image<T> channel(size_t c){
41acaf5d   David Mayerich   added a CUDA Gaus...
243
244
  
  		//create a new image
a2bf1d08   David Mayerich   general bug fixes...
245
  		image<T> r(X(), Y(), 1);
41acaf5d   David Mayerich   added a CUDA Gaus...
246
  
c8c976a9   David Mayerich   replaced CImg wit...
247
248
  		for(size_t x = 0; x < X(); x++){
  			for(size_t y = 0; y < Y(); y++){
8e2fb2b4   David Mayerich   fixed a segmentat...
249
  				r.img[r.idx(x, y, 0)] = img[idx(x, y, c)];
c8c976a9   David Mayerich   replaced CImg wit...
250
251
  			}
  		}
41acaf5d   David Mayerich   added a CUDA Gaus...
252
  
c8c976a9   David Mayerich   replaced CImg wit...
253
  		return r;
41acaf5d   David Mayerich   added a CUDA Gaus...
254
255
256
  
  	}
  
c8c976a9   David Mayerich   replaced CImg wit...
257
258
  	T& operator()(size_t x, size_t y, size_t c = 0){
  		return img[idx(x, y, c)];
3d0b6243   David Mayerich   fixed hsiproc bug...
259
260
261
262
263
264
265
  	}
  
  	/// Set all elements in the image to a given scalar value
  
  	/// @param v is the value used to set all values in the image
  	image<T> operator=(T v){
  
c8c976a9   David Mayerich   replaced CImg wit...
266
  		size_t N = size();
3d0b6243   David Mayerich   fixed hsiproc bug...
267
  
c8c976a9   David Mayerich   replaced CImg wit...
268
269
  		for(size_t n = 0; n < N; n++)
  			img[n] = v;
3d0b6243   David Mayerich   fixed hsiproc bug...
270
271
272
273
274
  
  		return *this;
  
  	}
  
f186dbda   Tianshu Cheng   header file for b...
275
276
277
278
279
  	/// Copy the given data to the specified channel
  
  	/// @param c is the channel number that the data will be copied to
  	/// @param buffer is a pointer to the image to be copied to channel c
  
c8c976a9   David Mayerich   replaced CImg wit...
280
  	void set_channel(T* buffer, size_t c){
6d30a707   Tianshu Cheng   add cuda/array_ad...
281
  
c8c976a9   David Mayerich   replaced CImg wit...
282
283
284
285
286
287
  		size_t x, y;
  		for(y = 0; y < Y(); y++){
  			for(x = 0; x < X(); x++){
  				img[idx(x, y, c)] = buffer[c];
  			}
  		}
6d30a707   Tianshu Cheng   add cuda/array_ad...
288
289
  	}
  
9d3ba0b1   David Mayerich   added stim::hsi a...
290
  	size_t channels(){
c8c976a9   David Mayerich   replaced CImg wit...
291
  		return C();
8b7be670   David Mayerich   implemented savin...
292
293
  	}
  
9d3ba0b1   David Mayerich   added stim::hsi a...
294
  	size_t width(){
c8c976a9   David Mayerich   replaced CImg wit...
295
  		return X();
8b7be670   David Mayerich   implemented savin...
296
297
  	}
  
9d3ba0b1   David Mayerich   added stim::hsi a...
298
  	size_t height(){
c8c976a9   David Mayerich   replaced CImg wit...
299
  		return Y();
3d0b6243   David Mayerich   fixed hsiproc bug...
300
301
  	}
  
6d30a707   Tianshu Cheng   add cuda/array_ad...
302
  	T* data(){
c8c976a9   David Mayerich   replaced CImg wit...
303
  		return img;
6d30a707   Tianshu Cheng   add cuda/array_ad...
304
305
  	}
  
7b3948ab   David Mayerich   added support for...
306
  	//returns the size (number of values) of the image
c8c976a9   David Mayerich   replaced CImg wit...
307
  	size_t size(){ return C() * X() * Y(); }
d32a1854   David Mayerich   added framework f...
308
  
faef7718   David Mayerich   updates to stim::...
309
  	/// Returns the number of nonzero values
9d3ba0b1   David Mayerich   added stim::hsi a...
310
  	size_t nnz(){
faef7718   David Mayerich   updates to stim::...
311
  
c8c976a9   David Mayerich   replaced CImg wit...
312
  		size_t N = X() * Y() * C();
faef7718   David Mayerich   updates to stim::...
313
  
c8c976a9   David Mayerich   replaced CImg wit...
314
315
316
  		size_t nz = 0;
  		for(size_t n = 0; n < N; n++)
  			if(img[n] != 0) nz++;
faef7718   David Mayerich   updates to stim::...
317
  
c8c976a9   David Mayerich   replaced CImg wit...
318
  		return nz;	//return the number of nonzero pixels
faef7718   David Mayerich   updates to stim::...
319
320
321
322
  
  	}
  
  	//this function returns indices of pixels that have nonzero values
9d3ba0b1   David Mayerich   added stim::hsi a...
323
  	std::vector<size_t> sparse_idx(){
faef7718   David Mayerich   updates to stim::...
324
  
c8c976a9   David Mayerich   replaced CImg wit...
325
  		std::vector<size_t> s;				//allocate an array
faef7718   David Mayerich   updates to stim::...
326
327
  		s.resize(nnz());					//allocate space in the array
  
c8c976a9   David Mayerich   replaced CImg wit...
328
329
  		size_t N = size();
  		//size_t C = channels();
faef7718   David Mayerich   updates to stim::...
330
  
c8c976a9   David Mayerich   replaced CImg wit...
331
  		//T* ptr = img.data();				//get a pointer to the image data
faef7718   David Mayerich   updates to stim::...
332
  
9d3ba0b1   David Mayerich   added stim::hsi a...
333
  		size_t i = 0;
c8c976a9   David Mayerich   replaced CImg wit...
334
335
336
337
  		for(size_t n = 0; n < N; n++){
  			if(img[n] != 0){
  				s[i] = n;
  				i++;
faef7718   David Mayerich   updates to stim::...
338
339
340
341
342
  			}
  		}
  
  		return s;			//return the index list
  	}
6d30a707   Tianshu Cheng   add cuda/array_ad...
343
  
1a224b6a   David Mayerich   fixed linux compa...
344
  
6d30a707   Tianshu Cheng   add cuda/array_ad...
345
  	/// Returns the maximum pixel value in the image
96f9b10f   Laila Saadatifard   change the header...
346
  	T maxv(){
c8c976a9   David Mayerich   replaced CImg wit...
347
348
  		T max_val = img[0];				//initialize the maximum value to the first one
  		size_t N = size();	//get the number of pixels
6d30a707   Tianshu Cheng   add cuda/array_ad...
349
  
c8c976a9   David Mayerich   replaced CImg wit...
350
  		for (size_t n=0; n<N; n++){		//for every value
6d30a707   Tianshu Cheng   add cuda/array_ad...
351
  
c8c976a9   David Mayerich   replaced CImg wit...
352
353
  			if (img[n] > max_val){			//if the value is higher than the current max
  				max_val = img[n];
1a224b6a   David Mayerich   fixed linux compa...
354
  			}
6d30a707   Tianshu Cheng   add cuda/array_ad...
355
356
  		}
  
1a224b6a   David Mayerich   fixed linux compa...
357
  		return max_val;
6d30a707   Tianshu Cheng   add cuda/array_ad...
358
  	}
d32a1854   David Mayerich   added framework f...
359
  
c8c976a9   David Mayerich   replaced CImg wit...
360
  	/// Returns the maximum pixel value in the image
96f9b10f   Laila Saadatifard   change the header...
361
  	T minv(){
c8c976a9   David Mayerich   replaced CImg wit...
362
363
  		T min_val = img[0];				//initialize the maximum value to the first one
  		size_t N = size();	//get the number of pixels
6d30a707   Tianshu Cheng   add cuda/array_ad...
364
  
c8c976a9   David Mayerich   replaced CImg wit...
365
366
367
  		for (size_t n=0; n<N; n++){		//for every value
  			if (img[n] < min_val){			//if the value is higher than the current max
  				min_val = img[n];
1a224b6a   David Mayerich   fixed linux compa...
368
  			}
6d30a707   Tianshu Cheng   add cuda/array_ad...
369
370
  		}
  
1a224b6a   David Mayerich   fixed linux compa...
371
  		return min_val;
6d30a707   Tianshu Cheng   add cuda/array_ad...
372
373
  	}
  
a2bf1d08   David Mayerich   general bug fixes...
374
375
376
377
378
379
  	/// Invert an image by calculating I1 = alpha - I0, where alpha is the maximum image value
  	image<T> invert(T white_val){
  		size_t N = size();						//calculate the total number of values in the image
  		image<T> r(X(), Y(), C());				//allocate space for the resulting image
  		for(size_t n = 0; n < N; n++)
  			r.img[n] = white_val - img[n];		//perform the inversion
1a224b6a   David Mayerich   fixed linux compa...
380
  
a2bf1d08   David Mayerich   general bug fixes...
381
382
  		return r;								//return the inverted image
  	}
e9a1b974   Pavel Govyadinov   imlemented Dr. Ma...
383
384
385
386
387
388
389
390
391
392
393
  	
  	/// Invert an image by calculating I1 = alpha - I0, where alpha is the maximum image value
  	image<T> invert(){
  		size_t N = size();						//calculate the total number of values in the image
  		image<T> r(X(), Y(), C());				//allocate space for the resulting image
  		T white_val = maxv();
  		for(size_t n = 0; n < N; n++)
  			r.img[n] = white_val - img[n];		//perform the inversion
  
  		return r;								//return the inverted image
  	}
a2bf1d08   David Mayerich   general bug fixes...
394
  
ae05c3e4   Pavel Govyadinov   Found an error wi...
395
  	///crops the image from x1 to x0 and y1 to y0 and returns a new (smaller) image.
ae05c3e4   Pavel Govyadinov   Found an error wi...
396
397
398
399
400
401
  	image<T> crop(int x0, int x1, int y0, int y1)
  	{
  		
  		image<T> ret(x1-x0, y1-y0, C());
  		int newWidth = x1-x0;
  		int destidx, srcidx;
fba6e7e3   Pavel Govyadinov   fixed image.h bug...
402
  		///for each row, cut what amount of data from the original and put it into the new copy.
e9a1b974   Pavel Govyadinov   imlemented Dr. Ma...
403
  		for(int i = 0; i < (y1-y0); i++)
ae05c3e4   Pavel Govyadinov   Found an error wi...
404
405
406
  		{
  			destidx = i*newWidth*C(); ///destination index one per each row
  			srcidx = ((i+(y0))*X()+x0)*C(); ///source index, one per each row.
e9a1b974   Pavel Govyadinov   imlemented Dr. Ma...
407
  			memcpy(&ret.img[destidx], &img[srcidx], sizeof(T)*newWidth*C());
ae05c3e4   Pavel Govyadinov   Found an error wi...
408
  		}		
ae05c3e4   Pavel Govyadinov   Found an error wi...
409
410
  		return ret;
  	}
a2bf1d08   David Mayerich   general bug fixes...
411
  
6d30a707   Tianshu Cheng   add cuda/array_ad...
412
  	image<T> srgb2lab(){
c8c976a9   David Mayerich   replaced CImg wit...
413
414
  		std::cout<<"ERROR stim::image::srgb2lab - function has been broken, re-implement."<<std::endl;
  		exit(1);
6d30a707   Tianshu Cheng   add cuda/array_ad...
415
416
417
  	}
  
  	image<T> convolve2(image<T> mask){
1a224b6a   David Mayerich   fixed linux compa...
418
  
c8c976a9   David Mayerich   replaced CImg wit...
419
420
  		std::cout<<"ERROR stim::image::convolve2 - function has been broken, and shouldn't really be in here."<<std::endl;
  		exit(1);
6d30a707   Tianshu Cheng   add cuda/array_ad...
421
  	}
d32a1854   David Mayerich   added framework f...
422
423
  
  
f186dbda   Tianshu Cheng   header file for b...
424
  	image<T> rotate(float angle, float cx, float cy){
c8c976a9   David Mayerich   replaced CImg wit...
425
426
  		std::cout<<"ERROR stim::image::rotate - function has been broken, and shouldn't really be in here."<<std::endl;
  		exit(1);
f186dbda   Tianshu Cheng   header file for b...
427
  	}
945ee13c   Laila Saadatifard   the get_list func...
428
  
ae05c3e4   Pavel Govyadinov   Found an error wi...
429
  
945ee13c   Laila Saadatifard   the get_list func...
430
431
  	// leila's code for non_interleaving data in 3D
  	//create an data set from an interleaved buffer
9d3ba0b1   David Mayerich   added stim::hsi a...
432
  	void set_interleaved3(T* buffer, size_t width, size_t height, size_t depth, size_t channels = 3){
c8c976a9   David Mayerich   replaced CImg wit...
433
434
  		std::cout<<"ERROR stim::image::set_interleaved3 - stim::image no longer supports 3D images."<<std::endl;
  		exit(1);
945ee13c   Laila Saadatifard   the get_list func...
435
  	}
1a224b6a   David Mayerich   fixed linux compa...
436
  
d32a1854   David Mayerich   added framework f...
437
438
  };
  
7b3948ab   David Mayerich   added support for...
439
440
  };		//end namespace stim
  
d32a1854   David Mayerich   added framework f...
441
442
  
  #endif