g4tools  5.4.0
png
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_png
5 #define tools_png
6 
7 #include <cstdio> //FILE,size_t
8 
9 #include <string>
10 
11 #include <tools/sout>
12 #include <tools/mnmx>
13 
14 #ifndef TOOLS_USE_OUREX_PNG
15 #include <png.h>
16 #else
17 #include <ourex_png.h> //enforce ourex png
18 #endif
19 
20 namespace tools {
21 namespace png {
22 
23 inline bool is(const std::string& a_file){
24  FILE* file = ::fopen(a_file.c_str(),"rb");
25  if(!file) return false; //if file does not exist, then it is not a png !
26  png_byte header[8]; // 8 is the maximum size that can be checked
27  size_t nitem = ::fread(header,1,8,file);
28  ::fclose(file);
29  if(nitem!=8) return false;
30  return ::png_sig_cmp(header,0,8)?false:true;
31 }
32 
33 }}
34 
35 #include <ostream>
36 
37 namespace tools {
38 namespace png {
39 
40 inline unsigned char* read_FILE(FILE* a_file,unsigned int& a_width,unsigned int& a_height,unsigned int& a_bpp) {
41 
42  png_byte header[8]; // 8 is the maximum size that can be checked
43  if(::fread(header,1,8,a_file)!=8) {
44  a_width = 0;
45  a_height = 0;
46  a_bpp = 0;
47  return 0;
48  }
49  if(::png_sig_cmp(header,0,8)) {
50  a_width = 0;
51  a_height = 0;
52  a_bpp = 0;
53  return 0;
54  }
55 
56  png_structp png_ptr =
57  ::png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
58  if(!png_ptr) {
59  a_width = 0;
60  a_height = 0;
61  a_bpp = 0;
62  return 0;
63  }
64 
65  png_infop info_ptr = ::png_create_info_struct(png_ptr);
66  if(!info_ptr) {
67  ::png_destroy_read_struct(&png_ptr,NULL,NULL);
68  a_width = 0;
69  a_height = 0;
70  a_bpp = 0;
71  return 0;
72  }
73 
74  if(::setjmp(png_jmpbuf(png_ptr))) {
75  ::png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
76  a_width = 0;
77  a_height = 0;
78  a_bpp = 0;
79  return 0;
80  }
81 
82  ::png_init_io(png_ptr,a_file);
83  ::png_set_sig_bytes(png_ptr,8);
84 
85  ::png_read_info(png_ptr,info_ptr);
86 
87  png_uint_32 width = ::png_get_image_width(png_ptr,info_ptr);
88  png_uint_32 height = ::png_get_image_height(png_ptr,info_ptr);
89  png_uint_32 rowbytes = ::png_get_rowbytes(png_ptr,info_ptr);
90  int bpp = width?rowbytes/width:0;
91 
92  if((width<=0)||(height<=0)||(bpp<=0)) {
93  ::png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
94  a_width = 0;
95  a_height = 0;
96  a_bpp = 0;
97  return 0;
98  }
99 
100  a_bpp = bpp; //avoid the clobbered -W warning.
101 
102  //png_byte color_type = info_ptr->color_type;
103  //info_ptr->bit_depth;
104 
105  //int number_of_passes = ::png_set_interlace_handling(png_ptr);
106  ::png_read_update_info(png_ptr,info_ptr);
107 
108  if(::setjmp(png_jmpbuf(png_ptr))) {
109  ::png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
110  a_width = 0;
111  a_height = 0;
112  a_bpp = 0;
113  return 0;
114  }
115 
116  unsigned char* buffer = new unsigned char[rowbytes * height];
117  if(!buffer) {
118  ::png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
119  a_height = 0;
120  a_width = 0;
121  a_bpp = 0;
122  return 0;
123  }
124 
125  {png_bytep* row_pointers = new png_bytep[height];
126  png_byte* pos = buffer+rowbytes*(height-1);
127  for(png_uint_32 y=0;y<height;y++) {
128  row_pointers[y] = pos;
129  pos -= rowbytes;
130  }
131  ::png_read_image(png_ptr,row_pointers);
132  delete [] row_pointers;}
133 
134  ::png_read_end(png_ptr,info_ptr);
135 
136  ::png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
137 
138  a_width = width;
139  a_height = height;
140  //a_bpp = bpp; //avoid the clobbered -W warning.
141 
142  return buffer;
143 }
144 
145 inline unsigned char* read(std::ostream& a_out,const std::string& a_file,unsigned int& a_width,unsigned int& a_height,unsigned int& a_bpp) {
146  //a_bpp = number of bytes per pixel.
147  FILE* file = fopen(a_file.c_str(),"rb");
148  if(!file) {
149  a_out << "tools::png::read :"
150  << " can't open file " << tools::sout(a_file) << "."
151  << std::endl;
152  a_width = 0;
153  a_height = 0;
154  a_bpp = 0;
155  return 0;
156  }
157  unsigned char* buffer = read_FILE(file,a_width,a_height,a_bpp);
158  if(!buffer) {
159  ::fclose(file);
160  a_width = 0;
161  a_height = 0;
162  a_bpp = 0;
163  a_out << "tools::png::read :"
164  << " read_FILE " << tools::sout(a_file) << " failed."
165  << std::endl;
166  return 0;
167  }
168  ::fclose(file);
169  return buffer;
170 }
171 
172 inline unsigned char* read_part(std::ostream& a_out,
173  const std::string& a_file,
174  unsigned int a_sx,unsigned int a_sy,
175  unsigned int a_sw,unsigned int a_sh,
176  unsigned int& a_rw,unsigned int& a_rh,
177  unsigned int& a_rbpp) {
178  a_out << "tools::png::read_part :"
179  << " not yet implemented."
180  << std::endl;
181  a_rw = 0;
182  a_rh = 0;
183  a_rbpp = 0;
184  return 0;
185 
186  unsigned int w,h,bpp;
187  unsigned char* buffer = read(a_out,a_file,w,h,bpp);
188  if(!buffer){
189  a_rw = 0;
190  a_rh = 0;
191  a_rbpp = 0;
192  return 0;
193  }
194 
195  if((a_sx>=w)||(a_sy>=h)){
196  delete [] buffer;
197  a_rw = 0;
198  a_rh = 0;
199  a_rbpp = 0;
200  return 0;
201  }
202 
203  // 012345
204  a_rw = tools::mn<unsigned int>(w-a_sx,a_sw);
205  a_rh = tools::mn<unsigned int>(h-a_sy,a_sh);
206  a_rbpp = bpp;
207 
208  if(!a_rw||!a_rh||!a_rbpp){
209  delete [] buffer;
210  a_rw = 0;
211  a_rh = 0;
212  a_rbpp = 0;
213  return 0;
214  }
215 
216  unsigned char* rb = new unsigned char[a_rw*a_rh*a_rbpp];
217  if(!rb) {
218  delete [] buffer;
219  a_rw = 0;
220  a_rh = 0;
221  a_rbpp = 0;
222  return 0;
223  }
224 
225  unsigned int rstride = a_rw * a_rbpp;
226  unsigned char* rpos = rb;
227 
228  unsigned int stride = w * bpp;
229  unsigned char* pos = buffer+a_sy*stride+a_sx*bpp;
230 
231  for(unsigned int j=0;j<a_rh;j++,rpos+=rstride,pos+=stride) {//j=0 -> bottom.
232  ::memcpy(rpos,pos,rstride);
233  }
234 
235  delete [] buffer;
236 
237  return rb;
238 }
239 
240 inline bool write_FILE(FILE* a_file,unsigned char* a_buffer,unsigned int a_width,unsigned int a_height,unsigned int a_bpp) {
241  //from gl2ps.c.
242  if((a_bpp!=3)&&(a_bpp!=4)) {
243  return false;
244  }
245 
246  png_structp png_ptr;
247  if(!(png_ptr = ::png_create_write_struct
248  (PNG_LIBPNG_VER_STRING,NULL,NULL,NULL))) return false;
249 
250  png_infop info_ptr;
251  if(!(info_ptr = ::png_create_info_struct(png_ptr))){
252  ::png_destroy_write_struct(&png_ptr,NULL);
253  return false;
254  }
255 
256  if(::setjmp(png_jmpbuf(png_ptr))) {
257  ::png_destroy_write_struct(&png_ptr,&info_ptr);
258  return false;
259  }
260 
261 #ifndef Z_DEFAULT_COMPRESSION
262 #define Z_DEFAULT_COMPRESSION (-1)
263 #endif
264 
265  ::png_init_io(png_ptr,a_file);
266  ::png_set_compression_level(png_ptr,Z_DEFAULT_COMPRESSION);
267  ::png_set_IHDR(png_ptr,info_ptr,a_width,a_height,8,
268  a_bpp==3?PNG_COLOR_TYPE_RGB:PNG_COLOR_TYPE_RGBA,
269  PNG_INTERLACE_NONE,
270  PNG_COMPRESSION_TYPE_BASE,PNG_FILTER_TYPE_BASE);
271  ::png_write_info(png_ptr,info_ptr);
272 
273  for(unsigned int row=0;row<a_height;row++){
274  unsigned char* pos = a_buffer+(a_height-1-row)*(a_width*a_bpp);
275  ::png_write_row(png_ptr,(png_bytep)pos);
276  }
277 
278  ::png_write_end(png_ptr,info_ptr);
279  ::png_destroy_write_struct(&png_ptr,&info_ptr);
280  return true;
281 }
282 
283 inline bool write(std::ostream& a_out,
284  const std::string& a_file,
285  unsigned char* a_buffer,
286  unsigned int a_width,
287  unsigned int a_height,
288  unsigned int a_bpp) {
289  FILE* file = ::fopen(a_file.c_str(),"wb");
290  if(!file) {
291  a_out << "tools::png::write :"
292  << " can't open file " << tools::sout(a_file) << "."
293  << std::endl;
294  return false;
295  }
296  if(!write_FILE(file,a_buffer,a_width,a_height,a_bpp)) {
297  ::fclose(file);
298  a_out << "tools::png::write :"
299  << " can't write file " << tools::sout(a_file) << "."
300  << std::endl;
301  return false;
302  }
303  ::fclose(file);
304  return true;
305 }
306 
307 inline bool infos_FILE(FILE* a_file,unsigned int& a_width,unsigned int& a_height,unsigned int& a_bpp) {
308  //a_bpp = number of bytes per pixel.
309  png_byte header[8]; // 8 is the maximum size that can be checked
310  if(::fread(header,1,8,a_file)!=8) {
311  a_width = 0;
312  a_height = 0;
313  a_bpp = 0;
314  return false;
315  }
316  if(::png_sig_cmp(header,0,8)) {
317  a_width = 0;
318  a_height = 0;
319  a_bpp = 0;
320  return false;
321  }
322 
323  png_structp png_ptr =
324  ::png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
325  if(!png_ptr) {
326  a_width = 0;
327  a_height = 0;
328  a_bpp = 0;
329  return false;
330  }
331 
332  png_infop info_ptr = ::png_create_info_struct(png_ptr);
333  if(!info_ptr) {
334  a_width = 0;
335  a_height = 0;
336  a_bpp = 0;
337  return false;
338  }
339 
340  if(::setjmp(png_jmpbuf(png_ptr))) {
341  a_width = 0;
342  a_height = 0;
343  a_bpp = 0;
344  return false;
345  }
346 
347  ::png_init_io(png_ptr,a_file);
348  ::png_set_sig_bytes(png_ptr,8);
349  ::png_read_info(png_ptr,info_ptr);
350 
351  png_uint_32 width = ::png_get_image_width(png_ptr,info_ptr);
352  png_uint_32 height = ::png_get_image_height(png_ptr,info_ptr);
353  png_uint_32 rowbytes = ::png_get_rowbytes(png_ptr,info_ptr);
354  a_bpp = width?rowbytes/width:0;
355 
356  ::png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
357 
358  a_width = width;
359  a_height = height;
360 
361  return true;
362 }
363 
364 inline bool infos(std::ostream& a_out,const std::string& a_file,unsigned int& a_width,unsigned int& a_height,unsigned int& a_bpp) {
365  if(!is(a_file)) {
366  a_out << "tools::png::infos :"
367  << " file " << a_file << " is not png."
368  << std::endl;
369  a_width = 0;
370  a_height = 0;
371  a_bpp = 0;
372  return false;
373  }
374 
375  FILE* file = ::fopen(a_file.c_str(),"rb");
376  if(!file) {
377  a_out << "tools::png::infos :"
378  << " can't open " << a_file
379  << std::endl;
380  a_width = 0;
381  a_height = 0;
382  a_bpp = 0;
383  return false;
384  }
385 
386  unsigned int w,h,bpp;
387  bool status = infos_FILE(file,w,h,bpp);
388 
389  ::fclose(file);
390 
391  if(!status) {
392  a_out << "tools::png::infos :"
393  << " problem reading " << a_file
394  << std::endl;
395  a_width = 0;
396  a_height = 0;
397  a_bpp = 0;
398  return false;
399  }
400 
401  a_width = w;
402  a_height = h;
403  a_bpp = bpp;
404  return true;
405 }
406 
407 }}
408 
409 #include <tools/xpm>
410 
411 namespace tools {
412 namespace png {
413 
414 inline bool to_xpm(std::ostream& a_out,const std::string& a_file,const std::string& a_name,bool a_verbose = false) {
415  return tools::xpm::to_xpm(a_out,a_file,a_name,read,a_verbose);
416 }
417 
418 }}
419 
420 #include <tools/image>
421 #include <vector>
422 
423 namespace tools {
424 namespace png {
425 
426 inline bool concatenate(std::ostream& a_out,
427  const std::vector<std::string>& a_files,
428  unsigned int a_cols,unsigned int a_rows,
429  unsigned int a_bw,unsigned int a_bh,
430  unsigned char a_bc,
431  const std::string& a_file) {
432  unsigned int wa,ha,bppa;
433  unsigned char* ba =
435  (a_out,a_files,a_cols,a_rows,a_bw,a_bh,a_bc,read,wa,ha,bppa);
436  if(!ba) {
437  a_out << "tools::png::concatenate :"
438  << " failed to concatenate all buffers."
439  << std::endl;
440  delete [] ba;
441  return false;
442  }
443 
444  FILE* file = ::fopen(a_file.c_str(),"wb");
445  if(!file) {
446  a_out << "tools::png::concatenate :"
447  << " can't open " << file << " for writing."
448  << std::endl;
449  delete [] ba;
450  return false;
451  }
452 
453  if(!write_FILE(file,ba,wa,ha,bppa)) {
454  a_out << "tools::png::concatenate :"
455  << " can't write " << a_file << "."
456  << std::endl;
457  delete [] ba;
458  ::fclose(file);
459  return false;
460  }
461 
462  delete [] ba;
463  ::fclose(file);
464  return true;
465 }
466 
467 class reader : public virtual tools::image::ireader {
468 public:
469  virtual tools::image::ireader* copy() const {return new reader(*this);}
470  virtual bool is(const std::string& a_file) const {return tools::png::is(a_file);}
471  virtual bool infos(std::ostream& a_out,const std::string& a_file,
472  unsigned int& a_width,unsigned int& a_height,unsigned int& a_bpp) const {
473  return tools::png::infos(a_out,a_file,a_width,a_height,a_bpp);
474  }
475  virtual unsigned char* read(std::ostream& a_out,const std::string& a_file,
476  unsigned int& a_width,unsigned int& a_height,unsigned int& a_bpp) const {
477  return tools::png::read(a_out,a_file,a_width,a_height,a_bpp);
478  }
479  virtual unsigned char* read_part(std::ostream& a_out,const std::string& a_file,
480  unsigned int a_sx,unsigned int a_sy,
481  unsigned int a_sw,unsigned int a_sh,
482  unsigned int& a_rw,unsigned int& a_rh,unsigned int& a_rbpp) const {
483  return tools::png::read_part(a_out,a_file,a_sx,a_sy,a_sw,a_sh,a_rw,a_rh,a_rbpp);
484  }
485 public:
486  reader(){}
487  virtual ~reader(){}
488 public:
489  reader(const reader&):ireader(){}
490  reader& operator=(const reader&){return *this;}
491 };
492 
493 }}
494 
495 #endif
tools::png::write_FILE
bool write_FILE(FILE *a_file, unsigned char *a_buffer, unsigned int a_width, unsigned int a_height, unsigned int a_bpp)
Definition: png:240
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
mnmx
tools::png::reader::~reader
virtual ~reader()
Definition: png:487
tools::png::write
bool write(std::ostream &a_out, const std::string &a_file, unsigned char *a_buffer, unsigned int a_width, unsigned int a_height, unsigned int a_bpp)
Definition: png:283
tools::png::infos
bool infos(std::ostream &a_out, const std::string &a_file, unsigned int &a_width, unsigned int &a_height, unsigned int &a_bpp)
Definition: png:364
tools::png::reader::operator=
reader & operator=(const reader &)
Definition: png:490
tools::png::to_xpm
bool to_xpm(std::ostream &a_out, const std::string &a_file, const std::string &a_name, bool a_verbose=false)
Definition: png:414
tools::png::is
bool is(const std::string &a_file)
Definition: png:23
tools::png::reader::reader
reader()
Definition: png:486
tools::png::read_part
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)
Definition: png:172
tools::png::concatenate
bool concatenate(std::ostream &a_out, const std::vector< std::string > &a_files, unsigned int a_cols, unsigned int a_rows, unsigned int a_bw, unsigned int a_bh, unsigned char a_bc, const std::string &a_file)
Definition: png:426
tools::sout
Definition: sout:17
tools::image::ireader
Definition: image_reader:15
tools::png::infos_FILE
bool infos_FILE(FILE *a_file, unsigned int &a_width, unsigned int &a_height, unsigned int &a_bpp)
Definition: png:307
tools::png::reader::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
Definition: png:475
tools::xpm::to_xpm
bool to_xpm(std::ostream &a_out, const std::string &a_file, const std::string &a_name, file_reader a_file_reader, bool a_verbose)
Definition: xpm:19
tools
inlined C code : ///////////////////////////////////
Definition: aida_ntuple:26
tools::png::reader::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
Definition: png:479
tools::png::reader::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
Definition: png:471
tools::png::reader::copy
virtual tools::image::ireader * copy() const
Definition: png:469
xpm
tools::png::read
unsigned char * read(std::ostream &a_out, const std::string &a_file, unsigned int &a_width, unsigned int &a_height, unsigned int &a_bpp)
Definition: png:145
tools::png::reader
Definition: png:467
Z_DEFAULT_COMPRESSION
#define Z_DEFAULT_COMPRESSION
tools::png::reader::is
virtual bool is(const std::string &a_file) const
Definition: png:470
tools::png::read_FILE
unsigned char * read_FILE(FILE *a_file, unsigned int &a_width, unsigned int &a_height, unsigned int &a_bpp)
Definition: png:40
image
tools::png::reader::reader
reader(const reader &)
Definition: png:489
sout