Commit 814eb2718806045f3ca7727674c6c9337d0e9e8f

Authored by David Mayerich
1 parent 0288346a

fixed problems with memory allocation in stim::image

stim/envi/bil.h
... ... @@ -884,7 +884,7 @@ public:
884 884 /// using the following indexing: i = p*B + b
885 885 /// @param matrix is the destination for the pixel data
886 886 /// @param mask is the mask
887   - bool sift(T* matrix, unsigned char* mask = NULL){
  887 + bool sift(T* matrix, unsigned char* mask = NULL, bool PROGRESS = false){
888 888 size_t Lbytes = sizeof(T) * X();
889 889 T* line = (T*) malloc( Lbytes ); //allocate space for a line
890 890  
... ... @@ -903,6 +903,7 @@ public:
903 903 pl++; //increment the pixel pointer
904 904 }
905 905 }
  906 + if(PROGRESS) progress = (double)( (y+1)*Z() + 1) / (double)(Y() * Z()) * 100;
906 907 }
907 908 p += pl; //add the line increment to the running pixel index
908 909 }
... ...
stim/envi/bip.h
... ... @@ -817,7 +817,7 @@ public:
817 817 /// using the following indexing: i = p*B + b
818 818 /// @param matrix is the destination for the pixel data
819 819 /// @param mask is the mask
820   - bool sift(T* matrix, unsigned char* mask = NULL){
  820 + bool sift(T* matrix, unsigned char* mask = NULL, bool PROGRESS = false){
821 821 size_t Bbytes = sizeof(T) * Z();
822 822 size_t XY = X() * Y();
823 823 T* band = (T*) malloc( Bbytes ); //allocate space for a line
... ... @@ -836,6 +836,7 @@ public:
836 836 }
837 837 else
838 838 file.seekg(Bbytes, std::ios::cur); //otherwise skip this band
  839 + if(PROGRESS) progress = (double)(xy+1) / (double)XY * 100;
839 840 }
840 841 return true;
841 842 }
... ...
stim/envi/bsq.h
... ... @@ -809,7 +809,7 @@ public:
809 809 /// using the following indexing: i = p*B + b
810 810 /// @param matrix is the destination for the pixel data
811 811 /// @param mask is the mask
812   - bool sift(T* matrix, unsigned char* mask = NULL){
  812 + bool sift(T* matrix, unsigned char* mask = NULL, bool PROGRESS = false){
813 813 unsigned long long XY = X() * Y(); //Number of XY pixels
814 814 unsigned long long L = XY * sizeof(T); //size of XY plane (in bytes)
815 815  
... ... @@ -827,9 +827,8 @@ public:
827 827 if(mask == NULL || mask[xy] != 0){ //if the pixel is valid
828 828 matrix[i*Z() + b] = band_image[xy]; //copy it to the appropriate point in the values[] array
829 829 i++;
830   - //std::cout<<i<<std::endl;
831 830 }
832   -
  831 + if(PROGRESS) progress = (double)(xy+1) / (double)XY * 100;
833 832 }
834 833 }
835 834  
... ...
stim/envi/envi.h
... ... @@ -670,13 +670,13 @@ public:
670 670 /// using the following indexing: i = b*P + p
671 671 /// @param matrix is the destination for the pixel data
672 672 /// @param p is the mask
673   - bool sift(void* matrix, unsigned char* p = NULL){
  673 + bool sift(void* matrix, unsigned char* p = NULL, bool PROGRESS = false){
674 674  
675 675 if (header.interleave == envi_header::BSQ){ //if the infile is bsq file
676 676 if (header.data_type == envi_header::float32)
677   - return ((bsq<float>*)file)->sift((float*)matrix, p);
  677 + return ((bsq<float>*)file)->sift((float*)matrix, p, PROGRESS);
678 678 else if (header.data_type == envi_header::float64)
679   - return ((bsq<double>*)file)->sift((double*)matrix, p);
  679 + return ((bsq<double>*)file)->sift((double*)matrix, p, PROGRESS);
680 680 else{
681 681 std::cout << "ERROR: unidentified data type" << std::endl;
682 682 exit(1);
... ... @@ -685,9 +685,9 @@ public:
685 685  
686 686 if (header.interleave == envi_header::BIP){
687 687 if (header.data_type == envi_header::float32)
688   - return ((bip<float>*)file)->sift((float*)matrix, p);
  688 + return ((bip<float>*)file)->sift((float*)matrix, p, PROGRESS);
689 689 else if (header.data_type == envi_header::float64)
690   - return ((bip<double>*)file)->sift((double*)matrix, p);
  690 + return ((bip<double>*)file)->sift((double*)matrix, p, PROGRESS);
691 691 else{
692 692 std::cout << "ERROR: unidentified data type" << std::endl;
693 693 exit(1);
... ... @@ -695,9 +695,9 @@ public:
695 695 }
696 696 if (header.interleave == envi_header::BIL){
697 697 if (header.data_type == envi_header::float32)
698   - return ((bil<float>*)file)->sift((float*)matrix, p);
  698 + return ((bil<float>*)file)->sift((float*)matrix, p, PROGRESS);
699 699 else if (header.data_type == envi_header::float64)
700   - return ((bil<double>*)file)->sift((double*)matrix, p);
  700 + return ((bil<double>*)file)->sift((double*)matrix, p, PROGRESS);
701 701 else{
702 702 std::cout << "ERROR: unidentified data type" << std::endl;
703 703 exit(1);
... ...
stim/image/image.h
... ... @@ -6,7 +6,6 @@
6 6 #include <vector>
7 7 #include <iostream>
8 8 #include <limits>
9   -#include <typeinfo>
10 9  
11 10 namespace stim{
12 11 /// This static class provides the STIM interface for loading, saving, and storing 2D images.
... ... @@ -25,8 +24,6 @@ class image{
25 24 size_t Y() const { return R[2]; }
26 25 size_t C() const { return R[0]; }
27 26  
28   - size_t bytes(){ return size() * sizeof(T); }
29   -
30 27 void init(){ //initializes all variables, assumes no memory is allocated
31 28 memset(R, 0, sizeof(size_t) * 3); //set the resolution and number of channels to zero
32 29 img = NULL;
... ... @@ -34,7 +31,6 @@ class image{
34 31  
35 32 void unalloc(){ //frees any resources associated with the image
36 33 if(img) free(img); //if memory has been allocated, free it
37   - img=NULL;
38 34 }
39 35  
40 36  
... ... @@ -45,16 +41,15 @@ class image{
45 41  
46 42 void allocate(){
47 43 unalloc();
48   - img = (T*) malloc( bytes() ); //allocate memory
49   - memset(img, 0, bytes());
  44 + img = (T*) malloc( sizeof(T) * R[0] * R[1] * R[2] ); //allocate memory
50 45 }
51 46  
52 47 void allocate(size_t x, size_t y, size_t c){ //allocate memory based on the resolution
53   - unalloc();
54 48 R[0] = c; R[1] = x; R[2] = y; //set the resolution
55 49 allocate(); //allocate memory
56 50 }
57 51  
  52 + size_t bytes(){ return size() * sizeof(T); }
58 53  
59 54 size_t idx(size_t x, size_t y, size_t c = 0){
60 55 return y * C() * X() + x * C() + c;
... ... @@ -62,23 +57,13 @@ class image{
62 57  
63 58  
64 59 int cv_type(){
65   - // The following is C++ 11 code, but causes problems on some compilers (ex. nvcc). Below is my best approximation to a solution
66   -
67   - //if(std::is_same<T, unsigned char>::value) return CV_MAKETYPE(CV_8U, (int)C());
68   - //if(std::is_same<T, char>::value) return CV_MAKETYPE(CV_8S, (int)C());
69   - //if(std::is_same<T, unsigned short>::value) return CV_MAKETYPE(CV_16U, (int)C());
70   - //if(std::is_same<T, short>::value) return CV_MAKETYPE(CV_16S, (int)C());
71   - //if(std::is_same<T, int>::value) return CV_MAKETYPE(CV_32S, (int)C());
72   - //if(std::is_same<T, float>::value) return CV_MAKETYPE(CV_32F, (int)C());
73   - //if(std::is_same<T, double>::value) return CV_MAKETYPE(CV_64F, (int)C());
74   -
75   - if(typeid(T) == typeid(unsigned char)) return CV_MAKETYPE(CV_8U, (int)C());
76   - if(typeid(T) == typeid(char)) return CV_MAKETYPE(CV_8S, (int)C());
77   - if(typeid(T) == typeid(unsigned short)) return CV_MAKETYPE(CV_16U, (int)C());
78   - if(typeid(T) == typeid(short)) return CV_MAKETYPE(CV_16S, (int)C());
79   - if(typeid(T) == typeid(int)) return CV_MAKETYPE(CV_32S, (int)C());
80   - if(typeid(T) == typeid(float)) return CV_MAKETYPE(CV_32F, (int)C());
81   - if(typeid(T) == typeid(double)) return CV_MAKETYPE(CV_64F, (int)C());
  60 + if(std::is_same<T, unsigned char>::value) return CV_MAKETYPE(CV_8U, (int)C());
  61 + if(std::is_same<T, char>::value) return CV_MAKETYPE(CV_8S, (int)C());
  62 + if(std::is_same<T, unsigned short>::value) return CV_MAKETYPE(CV_16U, (int)C());
  63 + if(std::is_same<T, short>::value) return CV_MAKETYPE(CV_16S, (int)C());
  64 + if(std::is_same<T, int>::value) return CV_MAKETYPE(CV_32S, (int)C());
  65 + if(std::is_same<T, float>::value) return CV_MAKETYPE(CV_32F, (int)C());
  66 + if(std::is_same<T, double>::value) return CV_MAKETYPE(CV_64F, (int)C());
82 67  
83 68 std::cout<<"ERROR in stim::image::cv_type - no valid data type found"<<std::endl;
84 69 exit(1);
... ... @@ -86,35 +71,23 @@ class image{
86 71  
87 72 /// Returns the value for "white" based on the dynamic range (assumes white is 1.0 for floating point images)
88 73 T white(){
89   - // The following is C++ 11 code, but causes problems on some compilers (ex. nvcc). Below is my best approximation to a solution
90   -
91   - //if(std::is_same<T, unsigned char>::value) return UCHAR_MAX;
92   - //if(std::is_same<T, unsigned short>::value) return SHRT_MAX;
93   - //if(std::is_same<T, unsigned>::value) return UINT_MAX;
94   - //if(std::is_same<T, unsigned long>::value) return ULONG_MAX;
95   - //if(std::is_same<T, unsigned long long>::value) return ULLONG_MAX;
96   - //if(std::is_same<T, float>::value) return 1.0f;
97   - //if(std::is_same<T, double>::value) return 1.0;
98   -
99   - if(typeid(T) == typeid(unsigned char)) return UCHAR_MAX;
100   - if(typeid(T) == typeid(unsigned short)) return SHRT_MAX;
101   - if(typeid(T) == typeid(unsigned)) return UINT_MAX;
102   - if(typeid(T) == typeid(unsigned long)) return ULONG_MAX;
103   - if(typeid(T) == typeid(unsigned long long)) return ULLONG_MAX;
104   - if(typeid(T) == typeid(float)) return 1.0f;
105   - if(typeid(T) == typeid(double)) return 1.0;
  74 + if(std::is_same<T, unsigned char>::value) return UCHAR_MAX;
  75 + if(std::is_same<T, unsigned short>::value) return SHRT_MAX;
  76 + if(std::is_same<T, unsigned>::value) return UINT_MAX;
  77 + if(std::is_same<T, unsigned long>::value) return ULONG_MAX;
  78 + if(std::is_same<T, unsigned long long>::value) return ULLONG_MAX;
  79 + if(std::is_same<T, float>::value) return 1.0f;
  80 + if(std::is_same<T, double>::value) return 1.0;
106 81  
107 82 std::cout<<"ERROR in stim::image::white - no white value known for this data type"<<std::endl;
108   - exit(1);
  83 +
109 84 }
110 85  
111 86  
112 87 public:
113 88  
114 89 /// Default constructor - creates an empty image object
115   - image(){
116   - init(); //initialize all variables to zero, don't allocate any memory
117   - }
  90 + image(){ init(); } //initialize all variables to zero, don't allocate any memory
118 91  
119 92 /// Constructor with a filename - loads the specified file
120 93 image(std::string filename){ //constructor initialize the image with an image file
... ... @@ -136,7 +109,7 @@ public:
136 109 }
137 110  
138 111 /// Copy constructor - duplicates an image object
139   - image(const stim::image<T> &I){
  112 + image(const stim::image<T>& I){
140 113 init();
141 114 allocate(I.X(), I.Y(), I.C());
142 115 memcpy(img, I.img, bytes());
... ... @@ -147,7 +120,16 @@ public:
147 120 free(img);
148 121 }
149 122  
  123 + /*stim::image<T> operator=(const stim::image<T>& I){
  124 + if(&I == this) //handle self-assignment
  125 + return *this;
  126 + allocate(I.X(), I.Y(), I.C());
  127 + memcpy(img, I.img, bytes());
  128 + return *this;
  129 + }*/
  130 +
150 131 stim::image<T>& operator=(const stim::image<T>& I){
  132 + init();
151 133 if(&I == this) //handle self-assignment
152 134 return *this;
153 135 allocate(I.X(), I.Y(), I.C());
... ... @@ -160,22 +142,15 @@ public:
160 142  
161 143 cv::Mat cvImage = cv::imread(filename, CV_LOAD_IMAGE_UNCHANGED); //use OpenCV to open the image file
162 144 if(!cvImage.data){
163   - std::cout<<"ERROR stim::image::load() - unable to find image "<<filename<<" ["<<__FILE__<<" (line "<<__LINE__<<")]"<<std::endl;
  145 + std::cout<<"ERROR stim::image::load() - unable to find image "<<filename<<std::endl;
164 146 exit(1);
165 147 }
166 148 allocate(cvImage.cols, cvImage.rows, cvImage.channels()); //allocate space for the image
167   - T* cv_ptr = (T*) cvImage.data;
168   - if(C() == 1)
169   - {
170   - //if this is a single-color image, just copy the data
171   - memcpy(img, cv_ptr, bytes());
172   - }
173   - if(C() == 3)
174   - { //if this is a 3-color image, OpenCV uses BGR interleaving
  149 + T* cv_ptr = (T*)cvImage.data;
  150 + if(C() == 1) //if this is a single-color image, just copy the data
  151 + memcpy(img, cv_ptr, bytes());
  152 + if(C() == 3) //if this is a 3-color image, OpenCV uses BGR interleaving
175 153 set_interleaved_bgr(cv_ptr, X(), Y());
176   - }
177   -
178   - cvImage.release();
179 154 }
180 155  
181 156 //save a file
... ... @@ -189,18 +164,16 @@ public:
189 164 get_interleaved_bgr(buffer);
190 165 cv::Mat cvImage((int)Y(), (int)X(), cv_type(), buffer);
191 166 cv::imwrite(filename, cvImage);
192   - cvImage.release();
193   - free(buffer);
194 167 }
195 168  
196 169 //create an image from an interleaved buffer
197   - void set_interleaved_rgb(T* buffer, size_t width, size_t height, size_t channels = 3){
198   - allocate(width, height, channels);
  170 + void set_interleaved_rgb(T* buffer, size_t width, size_t height){
  171 + allocate(width, height, 3);
199 172 memcpy(img, buffer, bytes());
200 173 }
201 174  
202   - void set_interleaved_bgr(T* buffer, size_t width, size_t height, size_t channels = 3){
203   - allocate(width, height, channels);
  175 + void set_interleaved_bgr(T* buffer, size_t width, size_t height){
  176 + allocate(width, height, 3);
204 177 for(size_t c = 0; c < C(); c++){ //copy directly
205 178 for(size_t y = 0; y < Y(); y++){
206 179 for(size_t x = 0; x < X(); x++){
... ... @@ -380,34 +353,6 @@ public:
380 353  
381 354 return r; //return the inverted image
382 355 }
383   -
384   - /// Invert an image by calculating I1 = alpha - I0, where alpha is the maximum image value
385   - image<T> invert(){
386   - size_t N = size(); //calculate the total number of values in the image
387   - image<T> r(X(), Y(), C()); //allocate space for the resulting image
388   - T white_val = maxv();
389   - for(size_t n = 0; n < N; n++)
390   - r.img[n] = white_val - img[n]; //perform the inversion
391   -
392   - return r; //return the inverted image
393   - }
394   -
395   - ///crops the image from x1 to x0 and y1 to y0 and returns a new (smaller) image.
396   - image<T> crop(int x0, int x1, int y0, int y1)
397   - {
398   -
399   - image<T> ret(x1-x0, y1-y0, C());
400   - int newWidth = x1-x0;
401   - int destidx, srcidx;
402   - ///for each row, cut what amount of data from the original and put it into the new copy.
403   - for(int i = 0; i < (y1-y0); i++)
404   - {
405   - destidx = i*newWidth*C(); ///destination index one per each row
406   - srcidx = ((i+(y0))*X()+x0)*C(); ///source index, one per each row.
407   - memcpy(&ret.img[destidx], &img[srcidx], sizeof(T)*newWidth*C());
408   - }
409   - return ret;
410   - }
411 356  
412 357 image<T> srgb2lab(){
413 358 std::cout<<"ERROR stim::image::srgb2lab - function has been broken, re-implement."<<std::endl;
... ... @@ -426,7 +371,6 @@ public:
426 371 exit(1);
427 372 }
428 373  
429   -
430 374 // leila's code for non_interleaving data in 3D
431 375 //create an data set from an interleaved buffer
432 376 void set_interleaved3(T* buffer, size_t width, size_t height, size_t depth, size_t channels = 3){
... ...