1 /* 2 */ 3 4 /* 5 6 Copyright (C) 2014 Ferrero Andrea 7 8 This program is free software: you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation, either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20 21 22 */ 23 24 /* 25 26 These files are distributed with PhotoFlow - http://aferrero2707.github.io/PhotoFlow/ 27 28 */ 29 30 #ifndef PF_ARRAY_2D_H 31 #define PF_ARRAY_2D_H 32 33 #include <stdlib.h> 34 #include <string> 35 #include <iostream> 36 37 //#define ARRAY2D_DEBUG 1 38 //#include "pixelmatrix.hh" 39 40 namespace PF { 41 42 43 template<class T> 44 class Array2D 45 { 46 unsigned int width, height; 47 // Offset of the start of the image data 48 unsigned int r_offset, c_offset; 49 50 unsigned int size_allocated; 51 52 public: 53 T* buf; 54 T** matrix; 55 // The matrix shifted according to the configured offset 56 // The () operator uses this one to return the pixel values 57 T** matrix_shifted; 58 59 public: 60 Array2D(); 61 ~Array2D(); 62 GetWidth()63 unsigned int GetWidth() { return width; } GetHeight()64 unsigned int GetHeight() { return height; } GetRowOffset()65 unsigned int GetRowOffset() { return r_offset; } GetColOffset()66 unsigned int GetColOffset() { return c_offset; } 67 SetWidth(unsigned int w)68 void SetWidth(unsigned int w) { width = w; } SetHeight(unsigned int h)69 void SetHeight(unsigned int h) { height = h; } SetRowOffset(unsigned int offs)70 void SetRowOffset(unsigned int offs) { r_offset = offs; } SetColOffset(unsigned int offs)71 void SetColOffset(unsigned int offs) { c_offset = offs; } 72 73 bool Init(unsigned int w, unsigned int h, unsigned int r_offset, unsigned int c_offset); 74 void Resize(unsigned int width, unsigned int height); 75 void SetRowColOffset(unsigned int roffs, unsigned int coffs); 76 void SetXYOffset(unsigned int xoffs, unsigned int yoffs); 77 void Reset(); 78 GetBuffer()79 T* GetBuffer() { return buf; } 80 T& Get(unsigned int r, unsigned int c); 81 T& GetLocal(unsigned int r, unsigned int c); 82 83 // use with indices operator [](int r)84 T* operator[](int r) { 85 T* ptr = matrix_shifted[r] + c_offset; 86 T* ptr2 = matrix[r-r_offset]; 87 //std::cout<<"r="<<r<<" r_offset="<<r_offset<<" ptr="<<ptr<<" ptr2="<<ptr2<<std::endl; 88 return matrix_shifted[r]; 89 } 90 91 92 // use as pointer to data operator T*()93 operator T*() 94 { 95 // only if owner this will return a valid pointer 96 return buf; 97 } 98 99 100 }; 101 102 103 template<class T> Array2D()104 Array2D<T>::Array2D() 105 { 106 buf = 0; 107 matrix = 0; 108 size_allocated = 0; 109 width = height = r_offset = c_offset = 0; 110 } 111 112 113 template<class T> ~Array2D()114 Array2D<T>::~Array2D() 115 { 116 #ifdef ARRAY2D_DEBUG 117 std::cout<<"Array2D<T>::~Array2D(): matrix="<<(void*)matrix<<" buf="<<(void*)buf<<std::endl; 118 #endif 119 if( matrix ) { 120 free( matrix ); 121 #ifdef ARRAY2D_DEBUG 122 std::cout<<"Array2D<T>::~Array2D(): matrix deallocated"<<std::endl; 123 #endif 124 } 125 if( buf ) { 126 free( buf ); 127 #ifdef ARRAY2D_DEBUG 128 std::cout<<"Array2D<T>::~Array2D(): buffer deallocated"<<std::endl; 129 #endif 130 } 131 } 132 133 134 template<class T> Reset()135 void Array2D<T>::Reset() 136 { 137 #ifdef ARRAY2D_DEBUG 138 std::cout<<"Array2D<T>::~Array2D(): matrix="<<(void*)matrix<<" buf="<<(void*)buf<<std::endl; 139 #endif 140 if( matrix ) { 141 free( matrix ); 142 matrix = NULL; 143 #ifdef ARRAY2D_DEBUG 144 std::cout<<"Array2D<T>::~Array2D(): matrix deallocated"<<std::endl; 145 #endif 146 } 147 if( buf ) { 148 free( buf ); 149 buf = NULL; 150 #ifdef ARRAY2D_DEBUG 151 std::cout<<"Array2D<T>::~Array2D(): buffer deallocated"<<std::endl; 152 #endif 153 } 154 } 155 156 157 template<class T> Init(unsigned int w,unsigned int h,unsigned int r_offset,unsigned int c_offset)158 bool Array2D<T>::Init(unsigned int w, unsigned int h, unsigned int r_offset, unsigned int c_offset) 159 { 160 if(buf && GetWidth()==w && GetHeight()==h && 161 r_offset == GetRowOffset() && c_offset == GetColOffset()) 162 return false; 163 164 /* 165 Main buffer initialization 166 */ 167 // Step 1: check if global buffer needs to be (re)allocated 168 unsigned int offs = c_offset; 169 unsigned int size_new = sizeof(T)*w*h; 170 #ifdef ARRAY2D_DEBUG 171 std::cout<<"Array2D<T>::Init("<<w<<","<<h<<","<<r_offset<<","<<c_offset<<"): size_allocated=" 172 <<size_allocated<<" size_new="<<size_new<<std::endl; 173 #endif 174 if(size_new > size_allocated) { 175 #ifdef ARRAY2D_DEBUG 176 std::cout<<"Array2D<T>::Init("<<w<<","<<h<<","<<r_offset<<","<<c_offset<<"): old buf="<<buf; 177 #endif 178 //Array2DManager::Ref().Allocate(size_new); 179 buf = (T*)realloc(buf,size_new); 180 size_allocated = size_new; 181 #ifdef ARRAY2D_DEBUG 182 std::cout<<" new buf="<<buf<<std::endl; 183 #endif 184 #ifdef ARRAY2D_DEBUG 185 std::cout<<" reallocated buffer"<<std::endl; 186 #endif 187 } 188 189 /* 190 Array2D initialization 191 */ 192 // Step 2: check if the row vector of the pixel matrix needs to be (re)allocated 193 if(GetHeight() != h) { 194 matrix = (T**)realloc(matrix, sizeof(T*)*h*2); 195 #ifdef ARRAY2D_DEBUG 196 std::cout<<" matrix reallocated."<<std::endl; 197 #endif 198 } 199 200 // Step 3: check if the row pointers need to be (re)assigned 201 if(GetWidth() != w || GetHeight() != h) { 202 for(int j = 0; j < (int)h; j++) { 203 matrix[j] = &(buf[j*w]); 204 #ifdef ARRAY2D_DEBUG 205 //std::cout<<" matrix["<<j<<"] = &(buf["<<j<<"*"<<w<<"])" 206 // <<std::endl; 207 #endif 208 } 209 } 210 211 212 #ifdef ARRAY2D_DEBUG 213 std::cout<<" r_offset="<<r_offset<<" c_offset="<<c_offset<<std::endl; 214 std::cout<<" GetRowOffset()="<<GetRowOffset()<<" GetColOffset()="<<GetColOffset()<<std::endl; 215 #endif 216 // Step 4: check if the shifted matrix needs to be (re)initialized 217 if(GetHeight() != h || r_offset != GetRowOffset()) { 218 matrix_shifted = (&(matrix[h])) - r_offset; 219 //matrix_shifted = matrix - r_offset; 220 #ifdef ARRAY2D_DEBUG 221 std::cout<<" matrix_shifted updated"<<std::endl; 222 #endif 223 } 224 if(GetHeight() != h || c_offset != GetColOffset()) { 225 for(int j = 0; j < (int)h; j++) { 226 matrix_shifted[j+r_offset] = matrix[j] - c_offset; 227 #ifdef ARRAY2D_DEBUG 228 //std::cout<<" matrix_shifted["<<j+r_offset<<"] = matrix["<<j<<"-"<<c_offset<<std::endl; 229 #endif 230 } 231 #ifdef ARRAY2D_DEBUG 232 std::cout<<" matrix_shifted rows updated"<<std::endl; 233 #endif 234 } 235 236 237 SetWidth(w); 238 SetHeight(h); 239 SetRowOffset(r_offset); 240 SetColOffset(c_offset); 241 #ifdef ARRAY2D_DEBUG 242 std::cout<<"Array2D initialization ended." 243 <<std::endl; 244 #endif 245 return true; 246 } 247 248 249 template<class T> Resize(unsigned int w,unsigned int h)250 void Array2D<T>::Resize(unsigned int w, unsigned int h) 251 { 252 Init(w,h,GetRowOffset(),GetColOffset()); 253 } 254 255 256 template<class T> SetRowColOffset(unsigned int roffs,unsigned int coffs)257 void Array2D<T>::SetRowColOffset(unsigned int roffs, unsigned int coffs) 258 { 259 Init(GetWidth(),GetHeight(),roffs,coffs); 260 } 261 262 263 template<class T> SetXYOffset(unsigned int xoffs,unsigned int yoffs)264 void Array2D<T>::SetXYOffset(unsigned int xoffs, unsigned int yoffs) 265 { 266 Init(GetWidth(),GetHeight(),yoffs,xoffs); 267 } 268 269 270 template<class T> Get(unsigned int r,unsigned int c)271 T& Array2D<T>::Get(unsigned int r, unsigned int c) 272 { 273 return matrix_shifted[r][c]; 274 } 275 276 277 template<class T> GetLocal(unsigned int r,unsigned int c)278 T& Array2D<T>::GetLocal(unsigned int r, unsigned int c) 279 { 280 return matrix[r][c]; 281 } 282 283 284 } 285 286 #endif 287