inlib
1.2.0
|
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved. 00002 // See the file inlib.license for terms. 00003 00004 #ifndef inlib_image 00005 #define inlib_image 00006 00007 #include <vector> 00008 #include <cstring> //memcpy 00009 00010 #include "mnmx" 00011 00012 namespace inlib { 00013 namespace image { 00014 00015 // give a set of cols*rows same size rgb-image and build 00016 // a big image : 00017 inline unsigned char* concatenate(unsigned char** a_buffers, 00018 unsigned int a_w,unsigned int a_h, 00019 unsigned int a_bpp, 00020 unsigned int a_cols,unsigned int a_rows, 00021 unsigned int a_bw,unsigned int a_bh, 00022 unsigned char a_bc, 00023 unsigned int& a_rw,unsigned int& a_rh){ 00024 00025 // assume a_buffers has a_cols*a_rows entries. 00026 // a_buffers[0] is bottom-left 00027 // a_row=0 is bottom. 00028 00029 unsigned wbw = a_w + 2*a_bw; 00030 unsigned hbh = a_h + 2*a_bh; 00031 00032 a_rw = wbw * a_cols; 00033 a_rh = hbh * a_rows; 00034 00035 //printf("debug : %d %d\n",a_rw,a_rh); 00036 00037 // on big concatenated image the below may fail : 00038 unsigned char* rb = new unsigned char[a_rh*a_rw*a_bpp]; 00039 if(!rb) {a_rw = 0;a_rh = 0;return 0;} 00040 00041 unsigned int wbw3 = wbw*a_bpp; 00042 unsigned int aw3 = a_w*a_bpp; 00043 00044 //copy tiles : 00045 unsigned int index = 0; 00046 for(unsigned int j=0;j<a_rows;j++) { 00047 for(unsigned int i=0;i<a_cols;i++) { 00048 unsigned char* tile = a_buffers[index]; 00049 00050 for(unsigned int r=0;r<hbh;r++) { 00051 unsigned char* pos = rb + (j*hbh+r)*a_rw*a_bpp + i*wbw*a_bpp; 00052 ::memset(pos,a_bc,wbw3); 00053 } 00054 00055 for(unsigned int r=0;r<a_h;r++) { 00056 unsigned char* pos = rb + (j*hbh+r+a_bh)*a_rw*a_bpp + 00057 (i*wbw+a_bw)*a_bpp; 00058 unsigned char* ptile = tile+r*aw3; 00059 for(unsigned int c=0;c<aw3;c++) *pos++ = *ptile++; 00060 } 00061 00062 index++; 00063 } 00064 } 00065 00066 return rb; 00067 } 00068 00069 /* 00070 inline unsigned char* expand(unsigned char* a_buffer, 00071 unsigned int a_w,unsigned int a_h, 00072 unsigned int a_factor) { 00073 if(!a_factor) return 0; 00074 if(a_factor==1) return a_buffer; //WARNING : same buffer. 00075 00076 unsigned int nw = a_w*a_factor; 00077 unsigned int nh = a_h*a_factor; 00078 00079 //std::cout << "debug :" 00080 // << " " << a_w << " " << a_h 00081 // << " " << a_rw << " " << a_rh 00082 // << std::endl; 00083 00084 unsigned char* nb = new unsigned char[nh*(nw*3)]; 00085 if(!nb) return 0; 00086 00087 for(unsigned int j=0;j<a_h;j++) { 00088 for(unsigned int i=0;i<a_w;i++) { 00089 //position in the original image. 00090 unsigned char* pos = a_buffer + j * (a_w * 3) + i*3; 00091 00092 for(unsigned int fr=0;fr<a_factor;fr++) { 00093 for(unsigned int fc=0;fc<a_factor;fc++) { 00094 //position in the new image. 00095 unsigned char* npos = 00096 nb + (j*a_factor+fr) * (nw * 3) + (i*a_factor+fc)*3; 00097 *npos = *pos; 00098 *(npos+1) = *(pos+1); 00099 *(npos+2) = *(pos+2); 00100 } 00101 } 00102 00103 } 00104 } 00105 00106 return nb; 00107 } 00108 00109 inline unsigned char* to_texture(unsigned char* a_buffer, 00110 unsigned int a_w,unsigned int a_h, 00111 bool a_expand, 00112 unsigned char a_r, 00113 unsigned char a_g, 00114 unsigned char a_b, 00115 unsigned int& a_rw,unsigned int& a_rh) { 00116 00117 if(a_expand) { 00118 // if a_w, a_h are not power of two, we expand 00119 // the image and fill new spaces with rgb. 00120 00121 // are a_w, a_h power of two ? 00122 a_rw = 2; 00123 while(true) {if(a_rw>=a_w) break;a_rw *=2;} 00124 a_rh = 2; 00125 while(true) {if(a_rh>=a_h) break;a_rh *=2;} 00126 00127 if((a_rw==a_w)&&(a_rh==a_h)) return a_buffer; //WARNING : same buffer. 00128 00129 //std::cout << "debug :" 00130 // << " " << a_w << " " << a_h 00131 // << " " << a_rw << " " << a_rh 00132 // << std::endl; 00133 00134 unsigned char* rb = new unsigned char[a_rh*(a_rw*3)]; 00135 if(!rb) {a_rw = 0;a_rh = 0;return 0;} 00136 00137 // initialize with given color : 00138 for(unsigned int j=0;j<a_rh;j++) { //j=0 -> bottom. 00139 unsigned char* pos = rb + j * (a_rw * 3); 00140 for(unsigned int i=0;i<a_rw;i++) { 00141 *pos = a_r;pos++; 00142 *pos = a_g;pos++; 00143 *pos = a_b;pos++; 00144 } 00145 } 00146 00147 // center : 00148 unsigned int col = (a_rw-a_w)/2; 00149 unsigned int row = (a_rh-a_h)/2; 00150 00151 // copy original image in a centered part of the new one : 00152 for(unsigned int j=0;j<a_h;j++) { 00153 unsigned char* pos = a_buffer + j * (a_w * 3); 00154 unsigned char* rpos = rb + (j+row) * (a_rw * 3) + col*3; 00155 ::memcpy(rpos,pos,a_w*3); 00156 } 00157 00158 return rb; 00159 } else { 00160 00161 // closest w,h power of two : 00162 unsigned int sw = 2; 00163 while(true) {if((sw*2)>a_w) break;sw *=2;} 00164 unsigned int sh = 2; 00165 while(true) {if((sh*2)>a_h) break;sh *=2;} 00166 00167 if((sw==a_w)&&(sh==a_h)) { 00168 a_rw = sw; 00169 a_rh = sh; 00170 return a_buffer; //WARNING : same buffer. 00171 } 00172 00173 unsigned int sx = (a_w-sw)/2; 00174 unsigned int sy = (a_h-sh)/2; 00175 00176 return inlib::image::get_part(a_buffer,a_w,a_h,sx,sy,sw,sh,a_rw,a_rh); 00177 00178 } 00179 00180 } 00181 */ 00182 00183 }} 00184 00185 #include <ostream> 00186 #include <string> 00187 00188 namespace inlib { 00189 namespace image { 00190 00191 typedef unsigned char* (*file_reader)(std::ostream&,const std::string&,unsigned int&,unsigned int&,unsigned int&); 00192 00193 inline unsigned char* concatenate(std::ostream& a_out, 00194 const std::vector<std::string>& a_files, 00195 unsigned int a_cols,unsigned int a_rows, 00196 unsigned int a_bw,unsigned int a_bh, 00197 unsigned char a_bc, 00198 file_reader a_file_reader, 00199 unsigned int& a_w,unsigned int& a_h, 00200 unsigned int& a_bpp) { 00201 // a_files[0] is cols=0, rows=0 00202 // a_files[1] is cols=1, rows=0 00203 // a_files[2] is cols=2, rows=0 00204 // ... 00205 // and row=0 is bottom of big image. 00206 00207 unsigned int number = a_cols*a_rows; 00208 if(number!=a_files.size()) { 00209 a_out << "inlib::image::concatenate :" 00210 << " bad number of files. " << number << " expected." 00211 << std::endl; 00212 a_bpp = a_w = a_h = 0; 00213 return 0; 00214 } 00215 if(a_files.empty()) { 00216 a_out << "inlib::image::concatenate :" 00217 << " list of files is empty." 00218 << std::endl; 00219 a_bpp = a_w = a_h = 0; 00220 return 0; 00221 } 00222 00223 unsigned int w1 = 0; 00224 unsigned int h1 = 0; 00225 unsigned int bpp1 = 0; 00226 00227 typedef unsigned char* buffer_t; 00228 buffer_t* bs = new buffer_t[number]; 00229 {for(unsigned int i=0;i<number;i++) {bs[i] = 0;}} 00230 00231 bool read_failed = false; 00232 unsigned int index = 0; 00233 for(unsigned int j=0;j<a_rows;j++) { 00234 for(unsigned int i=0;i<a_cols;i++) { 00235 const std::string& file = a_files[index]; 00236 unsigned int w,h,bpp; 00237 unsigned char* b = a_file_reader(a_out,file,w,h,bpp); 00238 if(!b) { 00239 a_out << "inlib::image::concatenate :" 00240 << " can't read " << file << " expected." 00241 << std::endl; 00242 read_failed = true; 00243 break; 00244 } 00245 if(!index) { 00246 w1 = w; 00247 h1 = h; 00248 bpp1 = bpp; 00249 } else { 00250 if(w!=w1) { 00251 a_out << "inlib::image::concatenate :" 00252 << " file " << file 00253 << " does not have same width image as the first file one." 00254 << " (" << w << "," << w1 << ")." 00255 << std::endl; 00256 delete [] b; 00257 read_failed = true; 00258 break; 00259 } 00260 if(h!=h1) { 00261 a_out << "inlib::image::concatenate :" 00262 << " file " << file 00263 << " does not have same height image as the first file one." 00264 << " (" << h << "," << h1 << ")." 00265 << std::endl; 00266 delete [] b; 00267 read_failed = true; 00268 break; 00269 } 00270 if(bpp!=bpp1) { 00271 a_out << "inlib::image::concatenate :" 00272 << " file " << file 00273 << " does not have same bytes per pixel as the first file one." 00274 << " (" << h << "," << h1 << ")." 00275 << std::endl; 00276 delete [] b; 00277 read_failed = true; 00278 break; 00279 } 00280 } 00281 00282 bs[index] = b; 00283 00284 index++; 00285 } 00286 if(read_failed) break; 00287 } 00288 00289 if(read_failed) { 00290 {for(unsigned int i=0;i<number;i++) {delete [] bs[i];}} 00291 a_bpp = a_w = a_h = 0; 00292 return 0; 00293 } 00294 00295 unsigned int wa,ha; 00296 unsigned char* ba = 00297 inlib::image::concatenate(bs,w1,h1,bpp1, 00298 a_cols,a_rows,a_bw,a_bh,a_bc,wa,ha); 00299 if(!ba) { 00300 a_out << "inlib::image::concatenate :" 00301 << " failed to concatenate all buffers." 00302 << std::endl; 00303 {for(unsigned int i=0;i<number;i++) {delete [] bs[i];}} 00304 a_bpp = a_w = a_h = 0; 00305 return 0; 00306 } 00307 00308 {for(unsigned int i=0;i<number;i++) {delete [] bs[i];}} 00309 00310 a_w = wa; 00311 a_h = ha; 00312 a_bpp = bpp1; 00313 return ba; 00314 } 00315 00316 #if defined(__CINT__) 00317 // something does not pass with the below. 00318 #else 00319 typedef unsigned char* (*reader)(FILE*,unsigned int&,unsigned int&); 00320 typedef bool(*writer)(FILE*,unsigned char*,unsigned int,unsigned int); 00321 00322 inline bool convert(std::ostream& a_out, 00323 const std::string& a_sin, 00324 reader a_reader, 00325 const std::string& a_sout, 00326 writer a_writer){ 00327 00328 FILE* fin = ::fopen(a_sin.c_str(),"rb"); 00329 if(!fin) { 00330 a_out << "inlib::image::convert :" 00331 << " can't open " << a_sin 00332 << std::endl; 00333 return false; 00334 } 00335 00336 unsigned int w,h; 00337 unsigned char* b = a_reader(fin,w,h); 00338 if(!b) { 00339 a_out << "inlib::image::convert :" 00340 << " can't read " << a_sin 00341 << std::endl; 00342 ::fclose(fin); 00343 return false; 00344 } 00345 ::fclose(fin); 00346 00347 FILE* fout = ::fopen(a_sout.c_str(),"wb"); 00348 if(!fout) { 00349 a_out << "inlib::image::convert :" 00350 << " can't open " << a_sout 00351 << std::endl; 00352 delete [] b; 00353 return false; 00354 } 00355 00356 if(!a_writer(fout,b,w,h)) { 00357 a_out << "inlib::image::convert :" 00358 << " can't write " << a_sout 00359 << std::endl; 00360 ::fclose(fout); 00361 delete [] b; 00362 return false; 00363 } 00364 ::fclose(fout); 00365 delete [] b; 00366 return true; 00367 } 00368 #endif 00369 00370 }} 00371 00372 #endif