Commit 814eb2718806045f3ca7727674c6c9337d0e9e8f
1 parent
0288346a
fixed problems with memory allocation in stim::image
Showing
5 changed files
with
50 additions
and
105 deletions
Show diff stats
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){ | ... | ... |