g4tools  5.4.0
image
Go to the documentation of this file.
1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
2 // See the file tools.license for terms.
3 
4 #ifndef tools_image
5 #define tools_image
6 
7 #include <vector>
8 #include <cstring> //memcpy
9 #include <cstdio> //fopen
10 
11 #include "forit"
12 
13 namespace tools {
14 namespace image {
15 
16 // give a set of cols*rows same size rgb-image and build
17 // a big image :
18 inline unsigned char* concatenate(unsigned char** a_buffers,
19  unsigned int a_w,unsigned int a_h,
20  unsigned int a_bpp,
21  unsigned int a_cols,unsigned int a_rows,
22  unsigned int a_bw,unsigned int a_bh,
23  unsigned char a_bc,
24  unsigned int& a_rw,unsigned int& a_rh){
25 
26  // assume a_buffers has a_cols*a_rows entries.
27  // a_buffers[0] is bottom-left
28  // a_row=0 is bottom.
29 
30  unsigned int wbw = a_w + 2*a_bw;
31  unsigned int hbh = a_h + 2*a_bh;
32 
33  a_rw = wbw * a_cols;
34  a_rh = hbh * a_rows;
35 
36  //printf("debug : %d %d\n",a_rw,a_rh);
37 
38  // on big concatenated image the below may fail :
39  unsigned char* rb = new unsigned char[a_rh*a_rw*a_bpp];
40  if(!rb) {a_rw = 0;a_rh = 0;return 0;}
41 
42  unsigned int wbw3 = wbw*a_bpp;
43  unsigned int aw3 = a_w*a_bpp;
44 
45  //copy tiles :
46  unsigned int index = 0;
47  for(unsigned int j=0;j<a_rows;j++) {
48  for(unsigned int i=0;i<a_cols;i++) {
49  unsigned char* tile = a_buffers[index];
50 
51  for(unsigned int r=0;r<hbh;r++) {
52  unsigned char* pos = rb + (j*hbh+r)*a_rw*a_bpp + i*wbw*a_bpp;
53  ::memset(pos,a_bc,wbw3);
54  }
55 
56  for(unsigned int r=0;r<a_h;r++) {
57  unsigned char* pos = rb + (j*hbh+r+a_bh)*a_rw*a_bpp + (i*wbw+a_bw)*a_bpp;
58  unsigned char* ptile = tile+r*aw3;
59  for(unsigned int c=0;c<aw3;c++,pos++,ptile++) *pos = *ptile;
60  }
61 
62  index++;
63  }
64  }
65 
66  return rb;
67 }
68 
69 }}
70 
71 #include <ostream>
72 #include <string>
73 
74 namespace tools {
75 namespace image {
76 
77 typedef unsigned char* (*file_reader)(std::ostream&,const std::string&,unsigned int&,unsigned int&,unsigned int&);
78 
79 inline unsigned char* concatenate(std::ostream& a_out,
80  const std::vector<std::string>& a_files,
81  unsigned int a_cols,unsigned int a_rows,
82  unsigned int a_bw,unsigned int a_bh,
83  unsigned char a_bc,
84  file_reader a_file_reader,
85  unsigned int& a_w,unsigned int& a_h,
86  unsigned int& a_bpp) {
87  // a_files[0] is cols=0, rows=0
88  // a_files[1] is cols=1, rows=0
89  // a_files[2] is cols=2, rows=0
90  // ...
91  // and row=0 is bottom of big image.
92 
93  unsigned int number = a_cols*a_rows;
94  if(number!=a_files.size()) {
95  a_out << "tools::image::concatenate :"
96  << " bad number of files. " << number << " expected."
97  << std::endl;
98  a_bpp = a_w = a_h = 0;
99  return 0;
100  }
101  if(a_files.empty()) {
102  a_out << "tools::image::concatenate :"
103  << " list of files is empty."
104  << std::endl;
105  a_bpp = a_w = a_h = 0;
106  return 0;
107  }
108 
109  unsigned int w1 = 0;
110  unsigned int h1 = 0;
111  unsigned int bpp1 = 0;
112 
113  typedef unsigned char* buffer_t;
114  buffer_t* bs = new buffer_t[number];
115  {for(unsigned int i=0;i<number;i++) {bs[i] = 0;}}
116 
117  bool read_failed = false;
118  unsigned int index = 0;
119  for(unsigned int j=0;j<a_rows;j++) {
120  for(unsigned int i=0;i<a_cols;i++) {
121  const std::string& file = a_files[index];
122  unsigned int w,h,bpp;
123  unsigned char* b = a_file_reader(a_out,file,w,h,bpp);
124  if(!b) {
125  a_out << "tools::image::concatenate :"
126  << " can't read " << file << " expected."
127  << std::endl;
128  read_failed = true;
129  break;
130  }
131  if(!index) {
132  w1 = w;
133  h1 = h;
134  bpp1 = bpp;
135  } else {
136  if(w!=w1) {
137  a_out << "tools::image::concatenate :"
138  << " file " << file
139  << " does not have same width image as the first file one."
140  << " (" << w << "," << w1 << ")."
141  << std::endl;
142  delete [] b;
143  read_failed = true;
144  break;
145  }
146  if(h!=h1) {
147  a_out << "tools::image::concatenate :"
148  << " file " << file
149  << " does not have same height image as the first file one."
150  << " (" << h << "," << h1 << ")."
151  << std::endl;
152  delete [] b;
153  read_failed = true;
154  break;
155  }
156  if(bpp!=bpp1) {
157  a_out << "tools::image::concatenate :"
158  << " file " << file
159  << " does not have same bytes per pixel as the first file one."
160  << " (" << h << "," << h1 << ")."
161  << std::endl;
162  delete [] b;
163  read_failed = true;
164  break;
165  }
166  }
167 
168  bs[index] = b;
169 
170  index++;
171  }
172  if(read_failed) break;
173  }
174 
175  if(read_failed) {
176  {for(unsigned int i=0;i<number;i++) {delete [] bs[i];}}
177  a_bpp = a_w = a_h = 0;
178  return 0;
179  }
180 
181  unsigned int wa,ha;
182  unsigned char* ba = image::concatenate(bs,w1,h1,bpp1,a_cols,a_rows,a_bw,a_bh,a_bc,wa,ha);
183  if(!ba) {
184  a_out << "tools::image::concatenate :"
185  << " failed to concatenate all buffers."
186  << std::endl;
187  {for(unsigned int i=0;i<number;i++) {delete [] bs[i];}}
188  a_bpp = a_w = a_h = 0;
189  return 0;
190  }
191 
192  {for(unsigned int i=0;i<number;i++) {delete [] bs[i];}}
193 
194  a_w = wa;
195  a_h = ha;
196  a_bpp = bpp1;
197  return ba;
198 }
199 
200 typedef unsigned char* (*reader)(FILE*,unsigned int&,unsigned int&);
201 typedef bool(*writer)(FILE*,unsigned char*,unsigned int,unsigned int);
202 
203 inline bool convert(std::ostream& a_out,
204  const std::string& a_sin,
205  reader a_reader,
206  const std::string& a_sout,
207  writer a_writer){
208 
209  FILE* fin = ::fopen(a_sin.c_str(),"rb");
210  if(!fin) {
211  a_out << "tools::image::convert :"
212  << " can't open " << a_sin
213  << std::endl;
214  return false;
215  }
216 
217  unsigned int w,h;
218  unsigned char* b = a_reader(fin,w,h);
219  if(!b) {
220  a_out << "tools::image::convert :"
221  << " can't read " << a_sin
222  << std::endl;
223  ::fclose(fin);
224  return false;
225  }
226  ::fclose(fin);
227 
228  FILE* fout = ::fopen(a_sout.c_str(),"wb");
229  if(!fout) {
230  a_out << "tools::image::convert :"
231  << " can't open " << a_sout
232  << std::endl;
233  delete [] b;
234  return false;
235  }
236 
237  if(!a_writer(fout,b,w,h)) {
238  a_out << "tools::image::convert :"
239  << " can't write " << a_sout
240  << std::endl;
241  ::fclose(fout);
242  delete [] b;
243  return false;
244  }
245  ::fclose(fout);
246  delete [] b;
247  return true;
248 }
249 
250 }}
251 
252 #include "image_reader"
253 
254 #include "sout"
255 
256 #include "S_STRING"
257 #ifdef TOOLS_MEM
258 #include "mem"
259 #endif
260 
261 namespace tools {
262 namespace image {
263 
264 class iterator {
265 public:
267 public:
268  virtual ~iterator(){}
269 public:
270  virtual unsigned int entries() const = 0;
271  virtual bool next() = 0;
272  virtual bool rewind() = 0;
273 public:
274  virtual unsigned int index() const = 0;
275  virtual unsigned char* read_image(unsigned int& a_w,unsigned int& a_h,
276  unsigned int& a_bpp) = 0;
277 };
278 
279 class iterator_reader : public virtual iterator {
280 public:
282 public:
283  //still virtual :
284  //virtual unsigned int entries() const = 0;
285  //virtual bool next() = 0;
286  //virtual bool rewind() = 0;
287  //virtual unsigned int index() const = 0;
288  virtual unsigned char* read_image(unsigned int& a_w,unsigned int& a_h,
289  unsigned int& a_bpp) {
290 
291  std::string file;
292  if(begin_file(file)) {
294  if((*it)->is(file)) {
295  unsigned char* buffer = _open(*(*it),file,a_w,a_h,a_bpp);
296  end_file(file);
297  return buffer;
298  }
299  }
300  end_file(file);
301  }
302  a_w = 0;a_h = 0;a_bpp = 0;
303  return 0;
304  }
305 public:
306  virtual bool begin_file(std::string&) = 0;
307  virtual bool end_file(const std::string&) = 0;
308 public:
309  iterator_reader(std::ostream& a_out,unsigned int a_limit)
310  :m_out(a_out)
311  ,m_limit(a_limit)
312  {
313 #ifdef TOOLS_MEM
314  mem::increment(s_class().c_str());
315 #endif
316  }
317  virtual ~iterator_reader(){
318  _clean();
319 #ifdef TOOLS_MEM
320  mem::decrement(s_class().c_str());
321 #endif
322  }
323 public:
325  :iterator(a_from)
326  ,m_out(a_from.m_out)
327  ,m_limit(a_from.m_limit)
328  {
329 #ifdef TOOLS_MEM
330  mem::increment(s_class().c_str());
331 #endif
332  _copy(a_from.m_readers);
333  }
335  if(&a_from==this) return *this;
336  m_limit = a_from.m_limit;
337  _copy(a_from.m_readers);
338  return *this;
339  }
340 public:
341  void add_reader(ireader* a_reader) {
342  m_readers.push_back(a_reader); //take ownership.
343  }
344 protected:
345  unsigned char* _open(const image::ireader& a_reader,
346  const std::string& a_path,
347  unsigned int& a_w,unsigned int& a_h,
348  unsigned int& a_bpp){
349  // permit to put in common code for jpeg and png.
350 
351  unsigned char* buffer = 0;
352 
353  if(m_limit) {
354  if(!a_reader.infos(m_out,a_path,a_w,a_h,a_bpp)) {
355  m_out << "tools::image::iterator_reader::_open :"
356  << " for file " << sout(a_path)
357  << " ireader::infos failed."
358  << std::endl;
359  a_w = 0;a_h = 0;a_bpp = 0;
360  return 0;
361  }
362  if((a_w*a_h*a_bpp)>m_limit) {
363 
364  //unsigned int sw;
365  //unsigned int sh;
366  //float aspect = float(w)/float(h);
367  //if(aspect>=1) {
368  // sh = 2;
369  // sw = aspect*sh;
370  //} else {
371  // sw = 2;
372  // sh = sw/aspect;
373  //}
374 
375  unsigned int sw = 2;
376  unsigned int sh = 2;
377  while(true) {
378  if(((2*sw)*(2*sh)*a_bpp)>m_limit) break;
379  sw *=2;
380  sh *=2;
381  }
382 
383  unsigned int sx = (a_w-sw)/2;
384  unsigned int sy = (a_h-sh)/2;
385 
386  buffer = a_reader.read_part
387  (m_out,a_path,sx,sy,sw,sh,a_w,a_h,a_bpp);
388  } else {
389  buffer = a_reader.read(m_out,a_path,a_w,a_h,a_bpp);
390  }
391  } else {
392  buffer = a_reader.read(m_out,a_path,a_w,a_h,a_bpp);
393  }
394 
395  if(!buffer) {
396  m_out << "tools::image::iterator_reader::_open :"
397  << " for file " << sout(a_path)
398  << " read failed."
399  << std::endl;
400  a_w = 0;a_h = 0;a_bpp = 0;
401  return 0;
402  }
403 
404  return buffer;
405  }
406 
407  void _clean() {
408  std::vector<ireader*>::iterator it;
409  for(it=m_readers.begin();it!=m_readers.end();) {
410  ireader* obj = *it;
411  it = m_readers.erase(it);
412  delete obj;
413  }
414  }
415  void _copy(const std::vector<ireader*>& a_from) {
416  _clean();
417  tools_vforcit(ireader*,a_from,it) m_readers.push_back((*it)->copy());
418  }
419 protected:
420  std::ostream& m_out;
421  unsigned int m_limit;
422  std::vector<ireader*> m_readers;
423 };
424 
425 }}
426 
427 #endif
image_reader
tools::image::concatenate
unsigned char * concatenate(unsigned char **a_buffers, unsigned int a_w, unsigned int a_h, unsigned int a_bpp, unsigned int a_cols, unsigned int a_rows, unsigned int a_bw, unsigned int a_bh, unsigned char a_bc, unsigned int &a_rw, unsigned int &a_rh)
Definition: image:18
tools::image::iterator_reader::_copy
void _copy(const std::vector< ireader * > &a_from)
Definition: image:415
tools::image::iterator::rewind
virtual bool rewind()=0
tools::image::iterator::entries
virtual unsigned int entries() const =0
tools::image::ireader::read
virtual unsigned char * read(std::ostream &a_out, const std::string &a_file, unsigned int &a_width, unsigned int &a_height, unsigned int &a_bpp) const =0
tools::image::iterator_reader::begin_file
virtual bool begin_file(std::string &)=0
tools::image::iterator::index
virtual unsigned int index() const =0
tools::image::iterator_reader::read_image
virtual unsigned char * read_image(unsigned int &a_w, unsigned int &a_h, unsigned int &a_bpp)
Definition: image:288
tools::image::iterator_reader::_clean
void _clean()
Definition: image:407
tools::image::iterator_reader::iterator_reader
iterator_reader(std::ostream &a_out, unsigned int a_limit)
Definition: image:309
tools::image::ireader::infos
virtual bool infos(std::ostream &a_out, const std::string &a_file, unsigned int &a_width, unsigned int &a_height, unsigned int &a_bpp) const =0
tools::image::iterator_reader::~iterator_reader
virtual ~iterator_reader()
Definition: image:317
tools::image::iterator_reader::add_reader
void add_reader(ireader *a_reader)
Definition: image:341
tools::image::reader
unsigned char *(* reader)(FILE *, unsigned int &, unsigned int &)
Definition: image:200
TOOLS_SCLASS
#define TOOLS_SCLASS(a_name)
Definition: S_STRING:41
tools::image::iterator_reader::m_readers
std::vector< ireader * > m_readers
Definition: image:422
mem
tools::image::iterator_reader
Definition: image:279
tools::image::file_reader
unsigned char *(* file_reader)(std::ostream &, const std::string &, unsigned int &, unsigned int &, unsigned int &)
Definition: image:77
tools::image::iterator::next
virtual bool next()=0
tools::sout
Definition: sout:17
tools::image::ireader
Definition: image_reader:15
tools::image::ireader::read_part
virtual unsigned char * read_part(std::ostream &a_out, const std::string &a_file, unsigned int a_sx, unsigned int a_sy, unsigned int a_sw, unsigned int a_sh, unsigned int &a_rw, unsigned int &a_rh, unsigned int &a_rbpp) const =0
tools
inlined C code : ///////////////////////////////////
Definition: aida_ntuple:26
tools::image::iterator_reader::_open
unsigned char * _open(const image::ireader &a_reader, const std::string &a_path, unsigned int &a_w, unsigned int &a_h, unsigned int &a_bpp)
Definition: image:345
S_STRING
tools::image::iterator::~iterator
virtual ~iterator()
Definition: image:268
tools::image::iterator_reader::m_limit
unsigned int m_limit
Definition: image:421
tools::image::convert
bool convert(std::ostream &a_out, const std::string &a_sin, reader a_reader, const std::string &a_sout, writer a_writer)
Definition: image:203
forit
tools::image::iterator_reader::m_out
std::ostream & m_out
Definition: image:420
tools::image::iterator_reader::operator=
iterator_reader & operator=(const iterator_reader &a_from)
Definition: image:334
tools::image::iterator::read_image
virtual unsigned char * read_image(unsigned int &a_w, unsigned int &a_h, unsigned int &a_bpp)=0
tools::image::writer
bool(* writer)(FILE *, unsigned char *, unsigned int, unsigned int)
Definition: image:201
tools_vforcit
#define tools_vforcit(a__T, a__v, a__it)
Definition: forit:7
tools::image::iterator_reader::iterator_reader
iterator_reader(const iterator_reader &a_from)
Definition: image:324
tools::image::iterator
Definition: image:264
tools::image::iterator_reader::end_file
virtual bool end_file(const std::string &)=0
sout