Visual Servoing Platform  version 3.3.1 under development (2020-06-03)
vpImageIo.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Read/write images.
33  *
34  * Authors:
35  * Eric Marchand
36  *
37  *****************************************************************************/
38 
44 #include <visp3/core/vpImage.h>
45 #include <visp3/core/vpImageConvert.h> //image conversion
46 #include <visp3/core/vpIoTools.h>
47 #include <visp3/io/vpImageIo.h>
48 
49 #if defined(_WIN32)
50 // Include WinSock2.h before windows.h to ensure that winsock.h is not
51 // included by windows.h since winsock.h and winsock2.h are incompatible
52 #include <WinSock2.h>
53 #include <windows.h>
54 #endif
55 
56 #if defined(VISP_HAVE_JPEG)
57 #include <jerror.h>
58 #include <jpeglib.h>
59 #endif
60 
61 #if defined(VISP_HAVE_PNG)
62 #include <png.h>
63 #endif
64 
65 #if !defined(VISP_HAVE_OPENCV)
66 #if !defined(VISP_HAVE_JPEG) || !defined(VISP_HAVE_PNG)
67 
68 #if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2)
69 # define VISP_HAVE_SSE2 1
70 #endif
71 
72 #ifndef VISP_HAVE_SSE2
73 # define STBI_NO_SIMD
74 #endif
75 
76 #define STB_IMAGE_IMPLEMENTATION
77 #include <stb_image.h>
78 
79 #define STB_IMAGE_WRITE_IMPLEMENTATION
80 #include <stb_image_write.h>
81 #endif
82 #endif
83 
84 void vp_decodeHeaderPNM(const std::string &filename, std::ifstream &fd, const std::string &magic, unsigned int &w,
85  unsigned int &h, unsigned int &maxval);
86 
87 #ifndef DOXYGEN_SHOULD_SKIP_THIS
88 
97 void vp_decodeHeaderPNM(const std::string &filename, std::ifstream &fd, const std::string &magic, unsigned int &w,
98  unsigned int &h, unsigned int &maxval)
99 {
100  std::string line;
101  unsigned int nb_elt = 4, cpt_elt = 0;
102  while (cpt_elt != nb_elt) {
103  // Skip empty lines or lines starting with # (comment)
104  while (std::getline(fd, line) && (line.compare(0, 1, "#") == 0 || line.size() == 0)) {
105  };
106 
107  if (fd.eof()) {
108  fd.close();
109  throw(vpImageException(vpImageException::ioError, "Cannot read header of file \"%s\"", filename.c_str()));
110  }
111 
112  std::vector<std::string> header = vpIoTools::splitChain(line, std::string(" "));
113 
114  if (header.size() == 0) {
115  fd.close();
116  throw(vpImageException(vpImageException::ioError, "Cannot read header of file \"%s\"", filename.c_str()));
117  }
118 
119  if (cpt_elt == 0) { // decode magic
120  if (header[0].compare(0, magic.size(), magic) != 0) {
121  fd.close();
122  throw(vpImageException(vpImageException::ioError, "\"%s\" is not a PNM file with magic number %s",
123  filename.c_str(), magic.c_str()));
124  }
125  cpt_elt++;
126  header.erase(header.begin(),
127  header.begin() + 1); // erase first element that is processed
128  }
129  while (header.size()) {
130  if (cpt_elt == 1) { // decode width
131  std::istringstream ss(header[0]);
132  ss >> w;
133  cpt_elt++;
134  header.erase(header.begin(),
135  header.begin() + 1); // erase first element that is processed
136  } else if (cpt_elt == 2) { // decode height
137  std::istringstream ss(header[0]);
138  ss >> h;
139  cpt_elt++;
140  header.erase(header.begin(),
141  header.begin() + 1); // erase first element that is processed
142  } else if (cpt_elt == 3) { // decode maxval
143  std::istringstream ss(header[0]);
144  ss >> maxval;
145  cpt_elt++;
146  header.erase(header.begin(),
147  header.begin() + 1); // erase first element that is processed
148  }
149  }
150  }
151 }
152 #endif
153 
154 vpImageIo::vpImageFormatType vpImageIo::getFormat(const std::string &filename)
155 {
156  std::string ext = vpImageIo::getExtension(filename);
157 
158  if (ext.compare(".PGM") == 0)
159  return FORMAT_PGM;
160  else if (ext.compare(".pgm") == 0)
161  return FORMAT_PGM;
162  else if (ext.compare(".PPM") == 0)
163  return FORMAT_PPM;
164  else if (ext.compare(".ppm") == 0)
165  return FORMAT_PPM;
166  else if (ext.compare(".JPG") == 0)
167  return FORMAT_JPEG;
168  else if (ext.compare(".jpg") == 0)
169  return FORMAT_JPEG;
170  else if (ext.compare(".JPEG") == 0)
171  return FORMAT_JPEG;
172  else if (ext.compare(".jpeg") == 0)
173  return FORMAT_JPEG;
174  else if (ext.compare(".PNG") == 0)
175  return FORMAT_PNG;
176  else if (ext.compare(".png") == 0)
177  return FORMAT_PNG;
178  // Formats supported by opencv
179  else if (ext.compare(".TIFF") == 0)
180  return FORMAT_TIFF;
181  else if (ext.compare(".tiff") == 0)
182  return FORMAT_TIFF;
183  else if (ext.compare(".TIF") == 0)
184  return FORMAT_TIFF;
185  else if (ext.compare(".tif") == 0)
186  return FORMAT_TIFF;
187  else if (ext.compare(".BMP") == 0)
188  return FORMAT_BMP;
189  else if (ext.compare(".bmp") == 0)
190  return FORMAT_BMP;
191  else if (ext.compare(".DIB") == 0)
192  return FORMAT_DIB;
193  else if (ext.compare(".dib") == 0)
194  return FORMAT_DIB;
195  else if (ext.compare(".PBM") == 0)
196  return FORMAT_PBM;
197  else if (ext.compare(".pbm") == 0)
198  return FORMAT_PBM;
199  else if (ext.compare(".SR") == 0)
200  return FORMAT_RASTER;
201  else if (ext.compare(".sr") == 0)
202  return FORMAT_RASTER;
203  else if (ext.compare(".RAS") == 0)
204  return FORMAT_RASTER;
205  else if (ext.compare(".ras") == 0)
206  return FORMAT_RASTER;
207  else if (ext.compare(".JP2") == 0)
208  return FORMAT_JPEG2000;
209  else if (ext.compare(".jp2") == 0)
210  return FORMAT_JPEG2000;
211  else
212  return FORMAT_UNKNOWN;
213 }
214 
215 // return the extension of the file including the dot
216 std::string vpImageIo::getExtension(const std::string &filename)
217 {
218  // extract the extension
219  size_t dot = filename.find_last_of(".");
220  std::string ext = filename.substr(dot, filename.size() - 1);
221  return ext;
222 }
223 
243 void vpImageIo::read(vpImage<unsigned char> &I, const std::string &filename)
244 {
245  bool exist = vpIoTools::checkFilename(filename);
246  if (!exist) {
247  std::string message = "Cannot read file: \"" + std::string(filename) + "\" doesn't exist";
249  }
250 
251  // Allows to use ~ symbol or env variables in path
252  std::string final_filename = vpIoTools::path(filename);
253 
254  bool try_opencv_reader = false;
255 
256  switch (getFormat(final_filename)) {
257  case FORMAT_PGM:
258  readPGM(I, final_filename);
259  break;
260  case FORMAT_PPM:
261  readPPM(I, final_filename);
262  break;
263  case FORMAT_JPEG:
264 #ifdef VISP_HAVE_JPEG
265  readJPEG(I, final_filename);
266 #else
267  try_opencv_reader = true;
268 #endif
269  break;
270  case FORMAT_PNG:
271 #if defined(VISP_HAVE_PNG)
272  readPNG(I, final_filename);
273 #else
274  try_opencv_reader = true;
275 #endif
276  break;
277  case FORMAT_TIFF:
278  case FORMAT_BMP:
279  case FORMAT_DIB:
280  case FORMAT_PBM:
281  case FORMAT_RASTER:
282  case FORMAT_JPEG2000:
283  case FORMAT_UNKNOWN:
284  try_opencv_reader = true;
285  break;
286  }
287 
288  if (try_opencv_reader) {
289 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
290  // std::cout << "Use opencv to read the image" << std::endl;
291  cv::Mat cvI = cv::imread(final_filename, cv::IMREAD_GRAYSCALE);
292  if (cvI.cols == 0 && cvI.rows == 0) {
293  std::string message = "Cannot read file \"" + std::string(final_filename) + "\": Image format not supported";
295  }
296  vpImageConvert::convert(cvI, I);
297 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
298  // std::cout << "Use opencv to read the image" << std::endl;
299  cv::Mat cvI = cv::imread(final_filename, CV_LOAD_IMAGE_GRAYSCALE);
300  if (cvI.cols == 0 && cvI.rows == 0) {
301  std::string message = "Cannot read file \"" + std::string(final_filename) + "\": Image format not supported";
303  }
304  vpImageConvert::convert(cvI, I);
305 #else
306  switch (getFormat(final_filename)) {
307  case FORMAT_JPEG:
308  readJPEG(I, final_filename);
309  break;
310  case FORMAT_PNG:
311  readPNG(I, final_filename);
312  break;
313  case FORMAT_BMP:
314  case FORMAT_TIFF:
315  case FORMAT_DIB:
316  case FORMAT_PBM:
317  case FORMAT_RASTER:
318  case FORMAT_JPEG2000:
319  case FORMAT_UNKNOWN:
320  default:
321  std::string message = "Cannot read file \"" + std::string(final_filename) + "\": Image format not supported";
323  }
324 #endif
325  }
326 }
327 
347 void vpImageIo::read(vpImage<vpRGBa> &I, const std::string &filename)
348 {
349  bool exist = vpIoTools::checkFilename(filename);
350  if (!exist) {
351  std::string message = "Cannot read file: \"" + std::string(filename) + "\" doesn't exist";
353  }
354  // Allows to use ~ symbol or env variables in path
355  std::string final_filename = vpIoTools::path(filename);
356 
357  bool try_opencv_reader = false;
358 
359  switch (getFormat(final_filename)) {
360  case FORMAT_PGM:
361  readPGM(I, final_filename);
362  break;
363  case FORMAT_PPM:
364  readPPM(I, final_filename);
365  break;
366  case FORMAT_JPEG:
367 #ifdef VISP_HAVE_JPEG
368  readJPEG(I, final_filename);
369 #else
370  try_opencv_reader = true;
371 #endif
372  break;
373  case FORMAT_PNG:
374 #if defined(VISP_HAVE_PNG)
375  readPNG(I, final_filename);
376 #else
377  try_opencv_reader = true;
378 #endif
379  break;
380  case FORMAT_TIFF:
381  case FORMAT_BMP:
382  case FORMAT_DIB:
383  case FORMAT_PBM:
384  case FORMAT_RASTER:
385  case FORMAT_JPEG2000:
386  case FORMAT_UNKNOWN:
387  try_opencv_reader = true;
388  break;
389  }
390 
391  if (try_opencv_reader) {
392 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
393  // std::cout << "Use opencv to read the image" << std::endl;
394  cv::Mat cvI = cv::imread(final_filename, cv::IMREAD_COLOR);
395  if (cvI.cols == 0 && cvI.rows == 0) {
396  std::string message = "Cannot read file \"" + std::string(final_filename) + "\": Image format not supported";
398  }
399  vpImageConvert::convert(cvI, I);
400 #elif VISP_HAVE_OPENCV_VERSION >= 0x020100
401  // std::cout << "Use opencv to read the image" << std::endl;
402  cv::Mat cvI = cv::imread(final_filename, CV_LOAD_IMAGE_COLOR);
403  if (cvI.cols == 0 && cvI.rows == 0) {
404  std::string message = "Cannot read file \"" + std::string(final_filename) + "\": Image format not supported";
406  }
407  vpImageConvert::convert(cvI, I);
408 #else
409  switch (getFormat(final_filename)) {
410  case FORMAT_JPEG:
411  readJPEG(I, final_filename);
412  break;
413  case FORMAT_PNG:
414  readPNG(I, final_filename);
415  break;
416  case FORMAT_BMP:
417  case FORMAT_TIFF:
418  case FORMAT_DIB:
419  case FORMAT_PBM:
420  case FORMAT_RASTER:
421  case FORMAT_JPEG2000:
422  case FORMAT_UNKNOWN:
423  default:
424  std::string message = "Cannot read file \"" + std::string(final_filename) + "\": Image format not supported";
426  }
427 #endif
428  }
429 }
430 
445 void vpImageIo::write(const vpImage<unsigned char> &I, const std::string &filename)
446 {
447  bool try_opencv_writer = false;
448 
449  switch (getFormat(filename)) {
450  case FORMAT_PGM:
451  writePGM(I, filename);
452  break;
453  case FORMAT_PPM:
454  writePPM(I, filename);
455  break;
456  case FORMAT_JPEG:
457 #ifdef VISP_HAVE_JPEG
458  writeJPEG(I, filename);
459 #else
460  try_opencv_writer = true;
461 #endif
462  break;
463  case FORMAT_PNG:
464 #ifdef VISP_HAVE_PNG
465  writePNG(I, filename);
466 #else
467  try_opencv_writer = true;
468 #endif
469  break;
470  case FORMAT_TIFF:
471  case FORMAT_BMP:
472  case FORMAT_DIB:
473  case FORMAT_PBM:
474  case FORMAT_RASTER:
475  case FORMAT_JPEG2000:
476  case FORMAT_UNKNOWN:
477  try_opencv_writer = true;
478  break;
479  }
480 
481  if (try_opencv_writer) {
482 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
483  // std::cout << "Use opencv to write the image" << std::endl;
484  cv::Mat cvI;
485  vpImageConvert::convert(I, cvI);
486  cv::imwrite(filename, cvI);
487 #else
488  switch (getFormat(filename)) {
489  case FORMAT_JPEG:
490  writeJPEG(I, filename);
491  break;
492  case FORMAT_PNG:
493  writePNG(I, filename);
494  break;
495  case FORMAT_BMP:
496  case FORMAT_TIFF:
497  case FORMAT_DIB:
498  case FORMAT_PBM:
499  case FORMAT_RASTER:
500  case FORMAT_JPEG2000:
501  case FORMAT_UNKNOWN:
502  default:
503  vpCERROR << "Cannot write file: Image format not supported..." << std::endl;
504  throw(vpImageException(vpImageException::ioError, "Cannot write file: Image format not supported"));
505  }
506 #endif
507  }
508 }
509 
524 void vpImageIo::write(const vpImage<vpRGBa> &I, const std::string &filename)
525 {
526  bool try_opencv_writer = false;
527 
528  switch (getFormat(filename)) {
529  case FORMAT_PGM:
530  writePGM(I, filename);
531  break;
532  case FORMAT_PPM:
533  writePPM(I, filename);
534  break;
535  case FORMAT_JPEG:
536 #ifdef VISP_HAVE_JPEG
537  writeJPEG(I, filename);
538 #else
539  try_opencv_writer = true;
540 #endif
541  break;
542  case FORMAT_PNG:
543 #ifdef VISP_HAVE_PNG
544  writePNG(I, filename);
545 #else
546  try_opencv_writer = true;
547 #endif
548  break;
549  case FORMAT_TIFF:
550  case FORMAT_BMP:
551  case FORMAT_DIB:
552  case FORMAT_PBM:
553  case FORMAT_RASTER:
554  case FORMAT_JPEG2000:
555  case FORMAT_UNKNOWN:
556  try_opencv_writer = true;
557  break;
558  }
559 
560  if (try_opencv_writer) {
561 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
562  // std::cout << "Use opencv to write the image" << std::endl;
563  cv::Mat cvI;
564  vpImageConvert::convert(I, cvI);
565  cv::imwrite(filename, cvI);
566 #else
567  switch (getFormat(filename)) {
568  case FORMAT_JPEG:
569  writeJPEG(I, filename);
570  break;
571  case FORMAT_PNG:
572  writePNG(I, filename);
573  break;
574  case FORMAT_BMP:
575  case FORMAT_TIFF:
576  case FORMAT_DIB:
577  case FORMAT_PBM:
578  case FORMAT_RASTER:
579  case FORMAT_JPEG2000:
580  case FORMAT_UNKNOWN:
581  default:
582  vpCERROR << "Cannot write file: Image format not supported..." << std::endl;
583  throw(vpImageException(vpImageException::ioError, "Cannot write file: Image format not supported"));
584  }
585 #endif
586  }
587 }
588 
589 //--------------------------------------------------------------------------
590 // PFM
591 //--------------------------------------------------------------------------
592 
602 void vpImageIo::writePFM(const vpImage<float> &I, const std::string &filename)
603 {
604  FILE *fd;
605 
606  // Test the filename
607  if (filename.empty()) {
608  throw(vpImageException(vpImageException::ioError, "Cannot write PFM image: filename empty"));
609  }
610 
611  fd = fopen(filename.c_str(), "wb");
612 
613  if (fd == NULL) {
614  throw(vpImageException(vpImageException::ioError, "Cannot create PFM file \"%s\"", filename.c_str()));
615  }
616 
617  // Write the head
618  fprintf(fd, "P8\n"); // Magic number
619  fprintf(fd, "%u %u\n", I.getWidth(), I.getHeight()); // Image size
620  fprintf(fd, "255\n"); // Max level
621 
622  // Write the bitmap
623  size_t ierr;
624  size_t nbyte = I.getWidth() * I.getHeight();
625 
626  ierr = fwrite(I.bitmap, sizeof(float), nbyte, fd);
627  if (ierr != nbyte) {
628  fclose(fd);
629  throw(vpImageException(vpImageException::ioError, "Cannot save PFM file \"%s\": only %d bytes over %d saved ",
630  filename.c_str(), ierr, nbyte));
631  }
632 
633  fflush(fd);
634  fclose(fd);
635 }
636 //--------------------------------------------------------------------------
637 // PGM
638 //--------------------------------------------------------------------------
639 
648 void vpImageIo::writePGM(const vpImage<unsigned char> &I, const std::string &filename)
649 {
650 
651  FILE *fd;
652 
653  // Test the filename
654  if (filename.empty()) {
655  throw(vpImageException(vpImageException::ioError, "Cannot create PGM file: filename empty"));
656  }
657 
658  fd = fopen(filename.c_str(), "wb");
659 
660  if (fd == NULL) {
661  throw(vpImageException(vpImageException::ioError, "Cannot create PGM file \"%s\"", filename.c_str()));
662  }
663 
664  // Write the head
665  fprintf(fd, "P5\n"); // Magic number
666  fprintf(fd, "%u %u\n", I.getWidth(), I.getHeight()); // Image size
667  fprintf(fd, "255\n"); // Max level
668 
669  // Write the bitmap
670  size_t ierr;
671  size_t nbyte = I.getWidth() * I.getHeight();
672 
673  ierr = fwrite(I.bitmap, sizeof(unsigned char), nbyte, fd);
674  if (ierr != nbyte) {
675  fclose(fd);
676  throw(vpImageException(vpImageException::ioError, "Cannot save PGM file \"%s\": only %d over %d bytes saved",
677  filename.c_str(), ierr, nbyte));
678  }
679 
680  fflush(fd);
681  fclose(fd);
682 }
683 
691 void vpImageIo::writePGM(const vpImage<short> &I, const std::string &filename)
692 {
694  unsigned int nrows = I.getHeight();
695  unsigned int ncols = I.getWidth();
696 
697  Iuc.resize(nrows, ncols);
698 
699  for (unsigned int i = 0; i < nrows * ncols; i++)
700  Iuc.bitmap[i] = (unsigned char)I.bitmap[i];
701 
702  vpImageIo::writePGM(Iuc, filename);
703 }
713 void vpImageIo::writePGM(const vpImage<vpRGBa> &I, const std::string &filename)
714 {
715 
716  FILE *fd;
717 
718  // Test the filename
719  if (filename.empty()) {
720  throw(vpImageException(vpImageException::ioError, "Cannot create PGM file: filename empty"));
721  }
722 
723  fd = fopen(filename.c_str(), "wb");
724 
725  if (fd == NULL) {
726  throw(vpImageException(vpImageException::ioError, "Cannot create PGM file \"%s\"", filename.c_str()));
727  }
728 
729  // Write the head
730  fprintf(fd, "P5\n"); // Magic number
731  fprintf(fd, "%u %u\n", I.getWidth(), I.getHeight()); // Image size
732  fprintf(fd, "255\n"); // Max level
733 
734  // Write the bitmap
735  size_t ierr;
736  size_t nbyte = I.getWidth() * I.getHeight();
737 
739  vpImageConvert::convert(I, Itmp);
740 
741  ierr = fwrite(Itmp.bitmap, sizeof(unsigned char), nbyte, fd);
742  if (ierr != nbyte) {
743  fclose(fd);
744  throw(vpImageException(vpImageException::ioError, "Cannot save PGM file \"%s\": only %d over %d bytes saved",
745  filename.c_str(), ierr, nbyte));
746  }
747 
748  fflush(fd);
749  fclose(fd);
750 }
751 
768 void vpImageIo::readPFM(vpImage<float> &I, const std::string &filename)
769 {
770  unsigned int w = 0, h = 0, maxval = 0;
771  unsigned int w_max = 100000, h_max = 100000, maxval_max = 255;
772  std::string magic("P8");
773 
774  std::ifstream fd(filename.c_str(), std::ios::binary);
775 
776  // Open the filename
777  if (!fd.is_open()) {
778  throw(vpImageException(vpImageException::ioError, "Cannot open file \"%s\"", filename.c_str()));
779  }
780 
781  vp_decodeHeaderPNM(filename, fd, magic, w, h, maxval);
782 
783  if (w > w_max || h > h_max) {
784  fd.close();
785  throw(vpException(vpException::badValue, "Bad image size in \"%s\"", filename.c_str()));
786  }
787  if (maxval > maxval_max) {
788  fd.close();
789  throw(vpImageException(vpImageException::ioError, "Bad maxval in \"%s\"", filename.c_str()));
790  }
791 
792  if ((h != I.getHeight()) || (w != I.getWidth())) {
793  I.resize(h, w);
794  }
795 
796  unsigned int nbyte = I.getHeight() * I.getWidth();
797  fd.read((char *)I.bitmap, sizeof(float) * nbyte);
798  if (!fd) {
799  fd.close();
800  throw(vpImageException(vpImageException::ioError, "Read only %d of %d bytes in file \"%s\"", fd.gcount(), nbyte,
801  filename.c_str()));
802  }
803 
804  fd.close();
805 }
806 
822 void vpImageIo::readPGM(vpImage<unsigned char> &I, const std::string &filename)
823 {
824  unsigned int w = 0, h = 0, maxval = 0;
825  unsigned int w_max = 100000, h_max = 100000, maxval_max = 255;
826  std::string magic("P5");
827 
828  std::ifstream fd(filename.c_str(), std::ios::binary);
829 
830  // Open the filename
831  if (!fd.is_open()) {
832  throw(vpImageException(vpImageException::ioError, "Cannot open file \"%s\"", filename.c_str()));
833  }
834 
835  vp_decodeHeaderPNM(filename, fd, magic, w, h, maxval);
836 
837  if (w > w_max || h > h_max) {
838  fd.close();
839  throw(vpException(vpException::badValue, "Bad image size in \"%s\"", filename.c_str()));
840  }
841  if (maxval > maxval_max) {
842  fd.close();
843  throw(vpImageException(vpImageException::ioError, "Bad maxval in \"%s\"", filename.c_str()));
844  }
845 
846  if ((h != I.getHeight()) || (w != I.getWidth())) {
847  I.resize(h, w);
848  }
849 
850  unsigned int nbyte = I.getHeight() * I.getWidth();
851  fd.read((char *)I.bitmap, nbyte);
852  if (!fd) {
853  fd.close();
854  throw(vpImageException(vpImageException::ioError, "Read only %d of %d bytes in file \"%s\"", fd.gcount(), nbyte,
855  filename.c_str()));
856  }
857 
858  fd.close();
859 }
860 
879 void vpImageIo::readPGM(vpImage<vpRGBa> &I, const std::string &filename)
880 {
882 
883  vpImageIo::readPGM(Itmp, filename);
884 
885  vpImageConvert::convert(Itmp, I);
886 }
887 
888 //--------------------------------------------------------------------------
889 // PPM
890 //--------------------------------------------------------------------------
891 
908 void vpImageIo::readPPM(vpImage<unsigned char> &I, const std::string &filename)
909 {
910  vpImage<vpRGBa> Itmp;
911 
912  vpImageIo::readPPM(Itmp, filename);
913 
914  vpImageConvert::convert(Itmp, I);
915 }
916 
928 void vpImageIo::readPPM(vpImage<vpRGBa> &I, const std::string &filename)
929 {
930  unsigned int w = 0, h = 0, maxval = 0;
931  unsigned int w_max = 100000, h_max = 100000, maxval_max = 255;
932  std::string magic("P6");
933 
934  std::ifstream fd(filename.c_str(), std::ios::binary);
935 
936  // Open the filename
937  if (!fd.is_open()) {
938  throw(vpImageException(vpImageException::ioError, "Cannot open file \"%s\"", filename.c_str()));
939  }
940 
941  vp_decodeHeaderPNM(filename, fd, magic, w, h, maxval);
942 
943  if (w > w_max || h > h_max) {
944  fd.close();
945  throw(vpException(vpException::badValue, "Bad image size in \"%s\"", filename.c_str()));
946  }
947  if (maxval > maxval_max) {
948  fd.close();
949  throw(vpImageException(vpImageException::ioError, "Bad maxval in \"%s\"", filename.c_str()));
950  }
951 
952  if ((h != I.getHeight()) || (w != I.getWidth())) {
953  I.resize(h, w);
954  }
955 
956  for (unsigned int i = 0; i < I.getHeight(); i++) {
957  for (unsigned int j = 0; j < I.getWidth(); j++) {
958  unsigned char rgb[3];
959  fd.read((char *)&rgb, 3);
960 
961  if (!fd) {
962  fd.close();
963  throw(vpImageException(vpImageException::ioError, "Read only %d of %d bytes in file \"%s\"",
964  (i * I.getWidth() + j) * 3 + fd.gcount(), I.getSize() * 3, filename.c_str()));
965  }
966 
967  I[i][j].R = rgb[0];
968  I[i][j].G = rgb[1];
969  I[i][j].B = rgb[2];
970  I[i][j].A = vpRGBa::alpha_default;
971  }
972  }
973 
974  fd.close();
975 }
976 
987 void vpImageIo::writePPM(const vpImage<unsigned char> &I, const std::string &filename)
988 {
989  vpImage<vpRGBa> Itmp;
990 
991  vpImageConvert::convert(I, Itmp);
992 
993  vpImageIo::writePPM(Itmp, filename);
994 }
995 
1003 void vpImageIo::writePPM(const vpImage<vpRGBa> &I, const std::string &filename)
1004 {
1005  FILE *f;
1006 
1007  // Test the filename
1008  if (filename.empty()) {
1009  throw(vpImageException(vpImageException::ioError, "Cannot create PPM file: filename empty"));
1010  }
1011 
1012  f = fopen(filename.c_str(), "wb");
1013 
1014  if (f == NULL) {
1015  throw(vpImageException(vpImageException::ioError, "Cannot create PPM file \"%s\"", filename.c_str()));
1016  }
1017 
1018  fprintf(f, "P6\n"); // Magic number
1019  fprintf(f, "%u %u\n", I.getWidth(), I.getHeight()); // Image size
1020  fprintf(f, "%d\n", 255); // Max level
1021 
1022  for (unsigned int i = 0; i < I.getHeight(); i++) {
1023  for (unsigned int j = 0; j < I.getWidth(); j++) {
1024  vpRGBa v = I[i][j];
1025  unsigned char rgb[3];
1026  rgb[0] = v.R;
1027  rgb[1] = v.G;
1028  rgb[2] = v.B;
1029 
1030  size_t res = fwrite(&rgb, 1, 3, f);
1031  if (res != 3) {
1032  fclose(f);
1033  throw(vpImageException(vpImageException::ioError, "cannot write file \"%s\"", filename.c_str()));
1034  }
1035  }
1036  }
1037 
1038  fflush(f);
1039  fclose(f);
1040 }
1041 
1042 //--------------------------------------------------------------------------
1043 // JPEG
1044 //--------------------------------------------------------------------------
1045 
1046 #if defined(VISP_HAVE_JPEG)
1047 
1055 void vpImageIo::writeJPEG(const vpImage<unsigned char> &I, const std::string &filename)
1056 {
1057  struct jpeg_compress_struct cinfo;
1058  struct jpeg_error_mgr jerr;
1059  FILE *file;
1060 
1061  cinfo.err = jpeg_std_error(&jerr);
1062  jpeg_create_compress(&cinfo);
1063 
1064  // Test the filename
1065  if (filename.empty()) {
1066  throw(vpImageException(vpImageException::ioError, "Cannot create JPEG file: filename empty"));
1067  }
1068 
1069  file = fopen(filename.c_str(), "wb");
1070 
1071  if (file == NULL) {
1072  throw(vpImageException(vpImageException::ioError, "Cannot create JPEG file \"%s\"", filename.c_str()));
1073  }
1074 
1075  unsigned int width = I.getWidth();
1076  unsigned int height = I.getHeight();
1077 
1078  jpeg_stdio_dest(&cinfo, file);
1079 
1080  cinfo.image_width = width;
1081  cinfo.image_height = height;
1082  cinfo.input_components = 1;
1083  cinfo.in_color_space = JCS_GRAYSCALE;
1084  jpeg_set_defaults(&cinfo);
1085 
1086  jpeg_start_compress(&cinfo, TRUE);
1087 
1088  unsigned char *line;
1089  line = new unsigned char[width];
1090  unsigned char *input = (unsigned char *)I.bitmap;
1091  while (cinfo.next_scanline < cinfo.image_height) {
1092  for (unsigned int i = 0; i < width; i++) {
1093  line[i] = *(input);
1094  input++;
1095  }
1096  jpeg_write_scanlines(&cinfo, &line, 1);
1097  }
1098 
1099  jpeg_finish_compress(&cinfo);
1100  jpeg_destroy_compress(&cinfo);
1101  delete[] line;
1102  fclose(file);
1103 }
1104 
1112 void vpImageIo::writeJPEG(const vpImage<vpRGBa> &I, const std::string &filename)
1113 {
1114  struct jpeg_compress_struct cinfo;
1115  struct jpeg_error_mgr jerr;
1116  FILE *file;
1117 
1118  cinfo.err = jpeg_std_error(&jerr);
1119  jpeg_create_compress(&cinfo);
1120 
1121  // Test the filename
1122  if (filename.empty()) {
1123  throw(vpImageException(vpImageException::ioError, "Cannot create JPEG file: filename empty"));
1124  }
1125 
1126  file = fopen(filename.c_str(), "wb");
1127 
1128  if (file == NULL) {
1129  throw(vpImageException(vpImageException::ioError, "Cannot create JPEG file \"%s\"", filename.c_str()));
1130  }
1131 
1132  unsigned int width = I.getWidth();
1133  unsigned int height = I.getHeight();
1134 
1135  jpeg_stdio_dest(&cinfo, file);
1136 
1137  cinfo.image_width = width;
1138  cinfo.image_height = height;
1139  cinfo.input_components = 3;
1140  cinfo.in_color_space = JCS_RGB;
1141  jpeg_set_defaults(&cinfo);
1142 
1143  jpeg_start_compress(&cinfo, TRUE);
1144 
1145  unsigned char *line;
1146  line = new unsigned char[3 * width];
1147  unsigned char *input = (unsigned char *)I.bitmap;
1148  while (cinfo.next_scanline < cinfo.image_height) {
1149  for (unsigned int i = 0; i < width; i++) {
1150  line[i * 3] = *(input);
1151  input++;
1152  line[i * 3 + 1] = *(input);
1153  input++;
1154  line[i * 3 + 2] = *(input);
1155  input++;
1156  input++;
1157  }
1158  jpeg_write_scanlines(&cinfo, &line, 1);
1159  }
1160 
1161  jpeg_finish_compress(&cinfo);
1162  jpeg_destroy_compress(&cinfo);
1163  delete[] line;
1164  fclose(file);
1165 }
1166 
1183 void vpImageIo::readJPEG(vpImage<unsigned char> &I, const std::string &filename)
1184 {
1185  struct jpeg_decompress_struct cinfo;
1186  struct jpeg_error_mgr jerr;
1187  FILE *file;
1188 
1189  cinfo.err = jpeg_std_error(&jerr);
1190  jpeg_create_decompress(&cinfo);
1191 
1192  // Test the filename
1193  if (filename.empty()) {
1194  throw(vpImageException(vpImageException::ioError, "Cannot read JPEG image: filename empty"));
1195  }
1196 
1197  file = fopen(filename.c_str(), "rb");
1198 
1199  if (file == NULL) {
1200  throw(vpImageException(vpImageException::ioError, "Cannot read JPEG file \"%s\"", filename.c_str()));
1201  }
1202 
1203  jpeg_stdio_src(&cinfo, file);
1204  jpeg_read_header(&cinfo, TRUE);
1205 
1206  unsigned int width = cinfo.image_width;
1207  unsigned int height = cinfo.image_height;
1208 
1209  if ((width != I.getWidth()) || (height != I.getHeight()))
1210  I.resize(height, width);
1211 
1212  jpeg_start_decompress(&cinfo);
1213 
1214  unsigned int rowbytes = cinfo.output_width * (unsigned int)(cinfo.output_components);
1215  JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, rowbytes, 1);
1216 
1217  if (cinfo.out_color_space == JCS_RGB) {
1218  vpImage<vpRGBa> Ic(height, width);
1219  unsigned char *output = (unsigned char *)Ic.bitmap;
1220  while (cinfo.output_scanline < cinfo.output_height) {
1221  jpeg_read_scanlines(&cinfo, buffer, 1);
1222  for (unsigned int i = 0; i < width; i++) {
1223  *(output++) = buffer[0][i * 3];
1224  *(output++) = buffer[0][i * 3 + 1];
1225  *(output++) = buffer[0][i * 3 + 2];
1226  *(output++) = vpRGBa::alpha_default;
1227  }
1228  }
1229  vpImageConvert::convert(Ic, I);
1230  }
1231 
1232  else if (cinfo.out_color_space == JCS_GRAYSCALE) {
1233  while (cinfo.output_scanline < cinfo.output_height) {
1234  unsigned int row = cinfo.output_scanline;
1235  jpeg_read_scanlines(&cinfo, buffer, 1);
1236  memcpy(I[row], buffer[0], rowbytes);
1237  }
1238  }
1239 
1240  jpeg_finish_decompress(&cinfo);
1241  jpeg_destroy_decompress(&cinfo);
1242  fclose(file);
1243 }
1244 
1263 void vpImageIo::readJPEG(vpImage<vpRGBa> &I, const std::string &filename)
1264 {
1265  struct jpeg_decompress_struct cinfo;
1266  struct jpeg_error_mgr jerr;
1267  FILE *file;
1268 
1269  cinfo.err = jpeg_std_error(&jerr);
1270  jpeg_create_decompress(&cinfo);
1271 
1272  // Test the filename
1273  if (filename.empty()) {
1274  throw(vpImageException(vpImageException::ioError, "Cannot read JPEG image: filename empty"));
1275  }
1276 
1277  file = fopen(filename.c_str(), "rb");
1278 
1279  if (file == NULL) {
1280  throw(vpImageException(vpImageException::ioError, "Cannot read JPEG file \"%s\"", filename.c_str()));
1281  }
1282 
1283  jpeg_stdio_src(&cinfo, file);
1284 
1285  jpeg_read_header(&cinfo, TRUE);
1286 
1287  unsigned int width = cinfo.image_width;
1288  unsigned int height = cinfo.image_height;
1289 
1290  if ((width != I.getWidth()) || (height != I.getHeight()))
1291  I.resize(height, width);
1292 
1293  jpeg_start_decompress(&cinfo);
1294 
1295  unsigned int rowbytes = cinfo.output_width * (unsigned int)(cinfo.output_components);
1296  JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, rowbytes, 1);
1297 
1298  if (cinfo.out_color_space == JCS_RGB) {
1299  unsigned char *output = (unsigned char *)I.bitmap;
1300  while (cinfo.output_scanline < cinfo.output_height) {
1301  jpeg_read_scanlines(&cinfo, buffer, 1);
1302  for (unsigned int i = 0; i < width; i++) {
1303  *(output++) = buffer[0][i * 3];
1304  *(output++) = buffer[0][i * 3 + 1];
1305  *(output++) = buffer[0][i * 3 + 2];
1306  *(output++) = vpRGBa::alpha_default;
1307  }
1308  }
1309  }
1310 
1311  else if (cinfo.out_color_space == JCS_GRAYSCALE) {
1312  vpImage<unsigned char> Ig(height, width);
1313 
1314  while (cinfo.output_scanline < cinfo.output_height) {
1315  unsigned int row = cinfo.output_scanline;
1316  jpeg_read_scanlines(&cinfo, buffer, 1);
1317  memcpy(Ig[row], buffer[0], rowbytes);
1318  }
1319 
1320  vpImageConvert::convert(Ig, I);
1321  }
1322 
1323  jpeg_finish_decompress(&cinfo);
1324  jpeg_destroy_decompress(&cinfo);
1325  fclose(file);
1326 }
1327 
1328 #elif defined(VISP_HAVE_OPENCV)
1329 
1337 void vpImageIo::writeJPEG(const vpImage<unsigned char> &I, const std::string &filename)
1338 {
1339 #if (VISP_HAVE_OPENCV_VERSION >= 0x020408)
1340  cv::Mat Ip;
1341  vpImageConvert::convert(I, Ip);
1342  cv::imwrite(filename.c_str(), Ip);
1343 #else
1344  IplImage *Ip = NULL;
1345  vpImageConvert::convert(I, Ip);
1346 
1347  cvSaveImage(filename.c_str(), Ip);
1348 
1349  cvReleaseImage(&Ip);
1350 #endif
1351 }
1352 
1360 void vpImageIo::writeJPEG(const vpImage<vpRGBa> &I, const std::string &filename)
1361 {
1362 #if (VISP_HAVE_OPENCV_VERSION >= 0x020408)
1363  cv::Mat Ip;
1364  vpImageConvert::convert(I, Ip);
1365  cv::imwrite(filename.c_str(), Ip);
1366 #else
1367  IplImage *Ip = NULL;
1368  vpImageConvert::convert(I, Ip);
1369 
1370  cvSaveImage(filename.c_str(), Ip);
1371 
1372  cvReleaseImage(&Ip);
1373 #endif
1374 }
1375 
1392 void vpImageIo::readJPEG(vpImage<unsigned char> &I, const std::string &filename)
1393 {
1394 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
1395  cv::Mat Ip = cv::imread(filename.c_str(), cv::IMREAD_GRAYSCALE);
1396  if (!Ip.empty())
1397  vpImageConvert::convert(Ip, I);
1398  else
1399  throw(vpImageException(vpImageException::ioError, "Can't read the image"));
1400 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020408)
1401  cv::Mat Ip = cv::imread(filename.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
1402  if (!Ip.empty())
1403  vpImageConvert::convert(Ip, I);
1404  else
1405  throw(vpImageException(vpImageException::ioError, "Can't read the image"));
1406 #else
1407  IplImage *Ip = NULL;
1408  Ip = cvLoadImage(filename.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
1409  if (Ip != NULL)
1410  vpImageConvert::convert(Ip, I);
1411  else
1412  throw(vpImageException(vpImageException::ioError, "Can't read the image"));
1413  cvReleaseImage(&Ip);
1414 #endif
1415 }
1416 
1435 void vpImageIo::readJPEG(vpImage<vpRGBa> &I, const std::string &filename)
1436 {
1437 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
1438  cv::Mat Ip = cv::imread(filename.c_str(), cv::IMREAD_GRAYSCALE);
1439  if (!Ip.empty())
1440  vpImageConvert::convert(Ip, I);
1441  else
1442  throw(vpImageException(vpImageException::ioError, "Can't read the image"));
1443 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020408)
1444  cv::Mat Ip = cv::imread(filename.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
1445  if (!Ip.empty())
1446  vpImageConvert::convert(Ip, I);
1447  else
1448  throw(vpImageException(vpImageException::ioError, "Can't read the image"));
1449 #else
1450  IplImage *Ip = NULL;
1451  Ip = cvLoadImage(filename.c_str(), CV_LOAD_IMAGE_COLOR);
1452  if (Ip != NULL)
1453  vpImageConvert::convert(Ip, I);
1454  else
1455  throw(vpImageException(vpImageException::ioError, "Can't read the image"));
1456  cvReleaseImage(&Ip);
1457 #endif
1458 }
1459 #else
1460 void vpImageIo::readJPEG(vpImage<unsigned char> &I, const std::string &filename)
1461 {
1462  int width = 0, height = 0, channels = 0;
1463  unsigned char *image = stbi_load(filename.c_str(), &width, &height, &channels, STBI_grey);
1464  if (image == NULL) {
1465  throw(vpImageException(vpImageException::ioError, "Can't read the image: %s", filename.c_str()));
1466  }
1467  I.init(image, static_cast<unsigned int>(height), static_cast<unsigned int>(width), true);
1468  stbi_image_free(image);
1469 }
1470 void vpImageIo::readJPEG(vpImage<vpRGBa> &I, const std::string &filename)
1471 {
1472  int width = 0, height = 0, channels = 0;
1473  unsigned char *image = stbi_load(filename.c_str(), &width, &height, &channels, STBI_rgb_alpha);
1474  if (image == NULL) {
1475  throw(vpImageException(vpImageException::ioError, "Can't read the image: %s", filename.c_str()));
1476  }
1477  I.init(reinterpret_cast<vpRGBa*>(image), static_cast<unsigned int>(height), static_cast<unsigned int>(width), true);
1478  stbi_image_free(image);
1479 }
1480 void vpImageIo::writeJPEG(const vpImage<unsigned char> &I, const std::string &filename)
1481 {
1482  int res = stbi_write_jpg(filename.c_str(), static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight()), STBI_grey,
1483  reinterpret_cast<void*>(I.bitmap), 90);
1484  if (res == 0) {
1485  throw(vpImageException(vpImageException::ioError, "JPEG write error"));
1486  }
1487 }
1488 void vpImageIo::writeJPEG(const vpImage<vpRGBa> &I, const std::string &filename)
1489 {
1490  int res = stbi_write_jpg(filename.c_str(), static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight()), STBI_rgb_alpha,
1491  reinterpret_cast<void*>(I.bitmap), 90);
1492  if (res == 0) {
1493  throw(vpImageException(vpImageException::ioError, "JEPG write error"));
1494  }
1495 }
1496 #endif
1497 
1498 //--------------------------------------------------------------------------
1499 // PNG
1500 //--------------------------------------------------------------------------
1501 
1502 #if defined(VISP_HAVE_PNG)
1503 
1511 void vpImageIo::writePNG(const vpImage<unsigned char> &I, const std::string &filename)
1512 {
1513  FILE *file;
1514 
1515  // Test the filename
1516  if (filename.empty()) {
1517  throw(vpImageException(vpImageException::ioError, "Cannot create PNG file: filename empty"));
1518  }
1519 
1520  file = fopen(filename.c_str(), "wb");
1521 
1522  if (file == NULL) {
1523  throw(vpImageException(vpImageException::ioError, "Cannot create PNG file \"%s\"", filename.c_str()));
1524  }
1525 
1526  /* create a png info struct */
1527  png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1528  if (!png_ptr) {
1529  fclose(file);
1530  vpERROR_TRACE("Error during png_create_write_struct()\n");
1531  throw(vpImageException(vpImageException::ioError, "PNG write error"));
1532  }
1533 
1534  png_infop info_ptr = png_create_info_struct(png_ptr);
1535  if (!info_ptr) {
1536  fclose(file);
1537  png_destroy_write_struct(&png_ptr, NULL);
1538  vpERROR_TRACE("Error during png_create_info_struct()\n");
1539  throw(vpImageException(vpImageException::ioError, "PNG write error"));
1540  }
1541 
1542  /* initialize the setjmp for returning properly after a libpng error occured
1543  */
1544  if (setjmp(png_jmpbuf(png_ptr))) {
1545  fclose(file);
1546  png_destroy_write_struct(&png_ptr, &info_ptr);
1547  vpERROR_TRACE("Error during init_io\n");
1548  throw(vpImageException(vpImageException::ioError, "PNG write error"));
1549  }
1550 
1551  /* setup libpng for using standard C fwrite() function with our FILE pointer
1552  */
1553  png_init_io(png_ptr, file);
1554 
1555  unsigned int width = I.getWidth();
1556  unsigned int height = I.getHeight();
1557  int bit_depth = 8;
1558  int color_type = PNG_COLOR_TYPE_GRAY;
1559  /* set some useful information from header */
1560 
1561  if (setjmp(png_jmpbuf(png_ptr))) {
1562  fclose(file);
1563  png_destroy_write_struct(&png_ptr, &info_ptr);
1564  vpERROR_TRACE("Error during write header\n");
1565  throw(vpImageException(vpImageException::ioError, "PNG write error"));
1566  }
1567 
1568  png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
1569  PNG_FILTER_TYPE_BASE);
1570 
1571  png_write_info(png_ptr, info_ptr);
1572 
1573  png_bytep *row_ptrs = new png_bytep[height];
1574  for (unsigned int i = 0; i < height; i++)
1575  row_ptrs[i] = new png_byte[width];
1576 
1577  unsigned char *input = (unsigned char *)I.bitmap;
1578 
1579  for (unsigned int i = 0; i < height; i++) {
1580  png_byte *row = row_ptrs[i];
1581  for (unsigned int j = 0; j < width; j++) {
1582  row[j] = *(input);
1583  input++;
1584  }
1585  }
1586 
1587  png_write_image(png_ptr, row_ptrs);
1588 
1589  png_write_end(png_ptr, NULL);
1590 
1591  for (unsigned int j = 0; j < height; j++)
1592  delete[] row_ptrs[j];
1593 
1594  delete[] row_ptrs;
1595 
1596  png_destroy_write_struct(&png_ptr, &info_ptr);
1597 
1598  fclose(file);
1599 }
1600 
1608 void vpImageIo::writePNG(const vpImage<vpRGBa> &I, const std::string &filename)
1609 {
1610  FILE *file;
1611 
1612  // Test the filename
1613  if (filename.empty()) {
1614  throw(vpImageException(vpImageException::ioError, "Cannot create PNG file: filename empty"));
1615  }
1616 
1617  file = fopen(filename.c_str(), "wb");
1618 
1619  if (file == NULL) {
1620  throw(vpImageException(vpImageException::ioError, "Cannot create PNG file \"%s\"", filename.c_str()));
1621  }
1622 
1623  /* create a png info struct */
1624  png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1625  if (!png_ptr) {
1626  fclose(file);
1627  vpERROR_TRACE("Error during png_create_write_struct()\n");
1628  throw(vpImageException(vpImageException::ioError, "PNG write error"));
1629  }
1630 
1631  png_infop info_ptr = png_create_info_struct(png_ptr);
1632  if (!info_ptr) {
1633  fclose(file);
1634  png_destroy_write_struct(&png_ptr, NULL);
1635  vpERROR_TRACE("Error during png_create_info_struct()\n");
1636  throw(vpImageException(vpImageException::ioError, "PNG write error"));
1637  }
1638 
1639  /* initialize the setjmp for returning properly after a libpng error occured
1640  */
1641  if (setjmp(png_jmpbuf(png_ptr))) {
1642  fclose(file);
1643  png_destroy_write_struct(&png_ptr, &info_ptr);
1644  vpERROR_TRACE("Error during init_io\n");
1645  throw(vpImageException(vpImageException::ioError, "PNG write error"));
1646  }
1647 
1648  /* setup libpng for using standard C fwrite() function with our FILE pointer
1649  */
1650  png_init_io(png_ptr, file);
1651 
1652  unsigned int width = I.getWidth();
1653  unsigned int height = I.getHeight();
1654  int bit_depth = 8;
1655  int color_type = PNG_COLOR_TYPE_RGB;
1656  /* set some useful information from header */
1657 
1658  if (setjmp(png_jmpbuf(png_ptr))) {
1659  fclose(file);
1660  png_destroy_write_struct(&png_ptr, &info_ptr);
1661  vpERROR_TRACE("Error during write header\n");
1662  throw(vpImageException(vpImageException::ioError, "PNG write error"));
1663  }
1664 
1665  png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
1666  PNG_FILTER_TYPE_BASE);
1667 
1668  png_write_info(png_ptr, info_ptr);
1669 
1670  png_bytep *row_ptrs = new png_bytep[height];
1671  for (unsigned int i = 0; i < height; i++)
1672  row_ptrs[i] = new png_byte[3 * width];
1673 
1674  unsigned char *input = (unsigned char *)I.bitmap;
1675  ;
1676 
1677  for (unsigned int i = 0; i < height; i++) {
1678  png_byte *row = row_ptrs[i];
1679  for (unsigned int j = 0; j < width; j++) {
1680  row[3 * j] = *(input);
1681  input++;
1682  row[3 * j + 1] = *(input);
1683  input++;
1684  row[3 * j + 2] = *(input);
1685  input++;
1686  input++;
1687  }
1688  }
1689 
1690  png_write_image(png_ptr, row_ptrs);
1691 
1692  png_write_end(png_ptr, NULL);
1693 
1694  for (unsigned int j = 0; j < height; j++)
1695  delete[] row_ptrs[j];
1696 
1697  delete[] row_ptrs;
1698 
1699  png_destroy_write_struct(&png_ptr, &info_ptr);
1700 
1701  fclose(file);
1702 }
1703 
1720 void vpImageIo::readPNG(vpImage<unsigned char> &I, const std::string &filename)
1721 {
1722  FILE *file;
1723  png_byte magic[8];
1724  // Test the filename
1725  if (filename.empty()) {
1726  throw(vpImageException(vpImageException::ioError, "Cannot read PNG image: filename empty"));
1727  }
1728 
1729  file = fopen(filename.c_str(), "rb");
1730 
1731  if (file == NULL) {
1732  throw(vpImageException(vpImageException::ioError, "Cannot read file \"%s\"", filename.c_str()));
1733  }
1734 
1735  /* read magic number */
1736  if (fread(magic, 1, sizeof(magic), file) != sizeof(magic)) {
1737  fclose(file);
1738  throw(vpImageException(vpImageException::ioError, "Cannot read magic number in file \"%s\"", filename.c_str()));
1739  }
1740 
1741  /* check for valid magic number */
1742  if (png_sig_cmp(magic, 0, sizeof(magic))) {
1743  fclose(file);
1744  throw(vpImageException(vpImageException::ioError, "Cannot read PNG file: \"%s\" is not a valid PNG image",
1745  filename.c_str()));
1746  }
1747 
1748  /* create a png read struct */
1749  // printf("version %s\n", PNG_LIBPNG_VER_STRING);
1750  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1751  if (png_ptr == NULL) {
1752  fprintf(stderr, "error: can't create a png read structure!\n");
1753  fclose(file);
1754  throw(vpImageException(vpImageException::ioError, "error reading png file"));
1755  }
1756 
1757  /* create a png info struct */
1758  png_infop info_ptr = png_create_info_struct(png_ptr);
1759  if (info_ptr == NULL) {
1760  fprintf(stderr, "error: can't create a png info structure!\n");
1761  fclose(file);
1762  png_destroy_read_struct(&png_ptr, NULL, NULL);
1763  throw(vpImageException(vpImageException::ioError, "error reading png file"));
1764  }
1765 
1766  /* initialize the setjmp for returning properly after a libpng error occured
1767  */
1768  if (setjmp(png_jmpbuf(png_ptr))) {
1769  fclose(file);
1770  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1771  vpERROR_TRACE("Error during init io\n");
1772  throw(vpImageException(vpImageException::ioError, "PNG read error"));
1773  }
1774 
1775  /* setup libpng for using standard C fread() function with our FILE pointer
1776  */
1777  png_init_io(png_ptr, file);
1778 
1779  /* tell libpng that we have already read the magic number */
1780  png_set_sig_bytes(png_ptr, sizeof(magic));
1781 
1782  /* read png info */
1783  png_read_info(png_ptr, info_ptr);
1784 
1785  unsigned int width = png_get_image_width(png_ptr, info_ptr);
1786  unsigned int height = png_get_image_height(png_ptr, info_ptr);
1787 
1788  unsigned int bit_depth, channels, color_type;
1789  /* get some useful information from header */
1790  bit_depth = png_get_bit_depth(png_ptr, info_ptr);
1791  channels = png_get_channels(png_ptr, info_ptr);
1792  color_type = png_get_color_type(png_ptr, info_ptr);
1793 
1794  /* convert index color images to RGB images */
1795  if (color_type == PNG_COLOR_TYPE_PALETTE)
1796  png_set_palette_to_rgb(png_ptr);
1797 
1798  /* convert 1-2-4 bits grayscale images to 8 bits grayscale. */
1799  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
1800  png_set_expand(png_ptr);
1801 
1802  // if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
1803  // png_set_tRNS_to_alpha (png_ptr);
1804 
1805  if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1806  png_set_strip_alpha(png_ptr);
1807 
1808  if (bit_depth == 16)
1809  png_set_strip_16(png_ptr);
1810  else if (bit_depth < 8)
1811  png_set_packing(png_ptr);
1812 
1813  /* update info structure to apply transformations */
1814  png_read_update_info(png_ptr, info_ptr);
1815 
1816  channels = png_get_channels(png_ptr, info_ptr);
1817 
1818  if ((width != I.getWidth()) || (height != I.getHeight()))
1819  I.resize(height, width);
1820 
1821  png_bytep *rowPtrs = new png_bytep[height];
1822 
1823  unsigned int stride = png_get_rowbytes(png_ptr, info_ptr);
1824  unsigned char *data = new unsigned char[stride * height];
1825 
1826  for (unsigned int i = 0; i < height; i++)
1827  rowPtrs[i] = (png_bytep)data + (i * stride);
1828 
1829  png_read_image(png_ptr, rowPtrs);
1830 
1831  vpImage<vpRGBa> Ic(height, width);
1832  unsigned char *output;
1833 
1834  switch (channels) {
1835  case 1:
1836  output = (unsigned char *)I.bitmap;
1837  for (unsigned int i = 0; i < width * height; i++) {
1838  *(output++) = data[i];
1839  }
1840  break;
1841 
1842  case 2:
1843  output = (unsigned char *)I.bitmap;
1844  for (unsigned int i = 0; i < width * height; i++) {
1845  *(output++) = data[i * 2];
1846  }
1847  break;
1848 
1849  case 3:
1850  output = (unsigned char *)Ic.bitmap;
1851  for (unsigned int i = 0; i < width * height; i++) {
1852  *(output++) = data[i * 3];
1853  *(output++) = data[i * 3 + 1];
1854  *(output++) = data[i * 3 + 2];
1855  *(output++) = vpRGBa::alpha_default;
1856  }
1857  vpImageConvert::convert(Ic, I);
1858  break;
1859 
1860  case 4:
1861  output = (unsigned char *)Ic.bitmap;
1862  for (unsigned int i = 0; i < width * height; i++) {
1863  *(output++) = data[i * 4];
1864  *(output++) = data[i * 4 + 1];
1865  *(output++) = data[i * 4 + 2];
1866  *(output++) = data[i * 4 + 3];
1867  }
1868  vpImageConvert::convert(Ic, I);
1869  break;
1870  }
1871 
1872  delete[](png_bytep) rowPtrs;
1873  delete[] data;
1874  png_read_end(png_ptr, NULL);
1875  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1876  fclose(file);
1877 }
1878 
1897 void vpImageIo::readPNG(vpImage<vpRGBa> &I, const std::string &filename)
1898 {
1899  FILE *file;
1900  png_byte magic[8];
1901 
1902  // Test the filename
1903  if (filename.empty()) {
1904  throw(vpImageException(vpImageException::ioError, "Cannot read PNG image: filename empty"));
1905  }
1906 
1907  file = fopen(filename.c_str(), "rb");
1908 
1909  if (file == NULL) {
1910  throw(vpImageException(vpImageException::ioError, "Cannot read file \"%s\"", filename.c_str()));
1911  }
1912 
1913  /* read magic number */
1914  if (fread(magic, 1, sizeof(magic), file) != sizeof(magic)) {
1915  fclose(file);
1916  throw(vpImageException(vpImageException::ioError, "Cannot read magic number in file \"%s\"", filename.c_str()));
1917  }
1918 
1919  /* check for valid magic number */
1920  if (png_sig_cmp(magic, 0, sizeof(magic))) {
1921  fclose(file);
1922  throw(vpImageException(vpImageException::ioError, "Cannot read PNG file: \"%s\" is not a valid PNG image",
1923  filename.c_str()));
1924  }
1925 
1926  /* create a png read struct */
1927  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1928  if (!png_ptr) {
1929  fclose(file);
1930  vpERROR_TRACE("Error during png_create_read_struct()\n");
1931  throw(vpImageException(vpImageException::ioError, "PNG read error"));
1932  }
1933 
1934  /* create a png info struct */
1935  png_infop info_ptr = png_create_info_struct(png_ptr);
1936  if (!info_ptr) {
1937  fclose(file);
1938  png_destroy_read_struct(&png_ptr, NULL, NULL);
1939  vpERROR_TRACE("Error during png_create_info_struct()\n");
1940  throw(vpImageException(vpImageException::ioError, "PNG read error"));
1941  }
1942 
1943  /* initialize the setjmp for returning properly after a libpng error occured
1944  */
1945  if (setjmp(png_jmpbuf(png_ptr))) {
1946  fclose(file);
1947  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1948  vpERROR_TRACE("Error during init io\n");
1949  throw(vpImageException(vpImageException::ioError, "PNG read error"));
1950  }
1951 
1952  /* setup libpng for using standard C fread() function with our FILE pointer
1953  */
1954  png_init_io(png_ptr, file);
1955 
1956  /* tell libpng that we have already read the magic number */
1957  png_set_sig_bytes(png_ptr, sizeof(magic));
1958 
1959  /* read png info */
1960  png_read_info(png_ptr, info_ptr);
1961 
1962  unsigned int width = png_get_image_width(png_ptr, info_ptr);
1963  unsigned int height = png_get_image_height(png_ptr, info_ptr);
1964 
1965  unsigned int bit_depth, channels, color_type;
1966  /* get some useful information from header */
1967  bit_depth = png_get_bit_depth(png_ptr, info_ptr);
1968  channels = png_get_channels(png_ptr, info_ptr);
1969  color_type = png_get_color_type(png_ptr, info_ptr);
1970 
1971  /* convert index color images to RGB images */
1972  if (color_type == PNG_COLOR_TYPE_PALETTE)
1973  png_set_palette_to_rgb(png_ptr);
1974 
1975  /* convert 1-2-4 bits grayscale images to 8 bits grayscale. */
1976  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
1977  png_set_expand(png_ptr);
1978 
1979  // if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
1980  // png_set_tRNS_to_alpha (png_ptr);
1981 
1982  if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1983  png_set_strip_alpha(png_ptr);
1984 
1985  if (bit_depth == 16)
1986  png_set_strip_16(png_ptr);
1987  else if (bit_depth < 8)
1988  png_set_packing(png_ptr);
1989 
1990  /* update info structure to apply transformations */
1991  png_read_update_info(png_ptr, info_ptr);
1992 
1993  channels = png_get_channels(png_ptr, info_ptr);
1994 
1995  if ((width != I.getWidth()) || (height != I.getHeight()))
1996  I.resize(height, width);
1997 
1998  png_bytep *rowPtrs = new png_bytep[height];
1999 
2000  unsigned int stride = png_get_rowbytes(png_ptr, info_ptr);
2001  unsigned char *data = new unsigned char[stride * height];
2002 
2003  for (unsigned int i = 0; i < height; i++)
2004  rowPtrs[i] = (png_bytep)data + (i * stride);
2005 
2006  png_read_image(png_ptr, rowPtrs);
2007 
2008  vpImage<unsigned char> Ig(height, width);
2009  unsigned char *output;
2010 
2011  switch (channels) {
2012  case 1:
2013  output = (unsigned char *)Ig.bitmap;
2014  for (unsigned int i = 0; i < width * height; i++) {
2015  *(output++) = data[i];
2016  }
2017  vpImageConvert::convert(Ig, I);
2018  break;
2019 
2020  case 2:
2021  output = (unsigned char *)Ig.bitmap;
2022  for (unsigned int i = 0; i < width * height; i++) {
2023  *(output++) = data[i * 2];
2024  }
2025  vpImageConvert::convert(Ig, I);
2026  break;
2027 
2028  case 3:
2029  output = (unsigned char *)I.bitmap;
2030  for (unsigned int i = 0; i < width * height; i++) {
2031  *(output++) = data[i * 3];
2032  *(output++) = data[i * 3 + 1];
2033  *(output++) = data[i * 3 + 2];
2034  *(output++) = vpRGBa::alpha_default;
2035  }
2036  break;
2037 
2038  case 4:
2039  output = (unsigned char *)I.bitmap;
2040  for (unsigned int i = 0; i < width * height; i++) {
2041  *(output++) = data[i * 4];
2042  *(output++) = data[i * 4 + 1];
2043  *(output++) = data[i * 4 + 2];
2044  *(output++) = data[i * 4 + 3];
2045  }
2046  break;
2047  }
2048 
2049  delete[](png_bytep) rowPtrs;
2050  delete[] data;
2051  png_read_end(png_ptr, NULL);
2052  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
2053  fclose(file);
2054 }
2055 
2056 #elif defined(VISP_HAVE_OPENCV)
2057 
2065 void vpImageIo::writePNG(const vpImage<unsigned char> &I, const std::string &filename)
2066 {
2067 #if (VISP_HAVE_OPENCV_VERSION >= 0x020408)
2068  cv::Mat Ip;
2069  vpImageConvert::convert(I, Ip);
2070  cv::imwrite(filename.c_str(), Ip);
2071 #else
2072  IplImage *Ip = NULL;
2073  vpImageConvert::convert(I, Ip);
2074 
2075  cvSaveImage(filename.c_str(), Ip);
2076 
2077  cvReleaseImage(&Ip);
2078 #endif
2079 }
2080 
2088 void vpImageIo::writePNG(const vpImage<vpRGBa> &I, const std::string &filename)
2089 {
2090 #if (VISP_HAVE_OPENCV_VERSION >= 0x020408)
2091  cv::Mat Ip;
2092  vpImageConvert::convert(I, Ip);
2093  cv::imwrite(filename.c_str(), Ip);
2094 #else
2095  IplImage *Ip = NULL;
2096  vpImageConvert::convert(I, Ip);
2097 
2098  cvSaveImage(filename.c_str(), Ip);
2099 
2100  cvReleaseImage(&Ip);
2101 #endif
2102 }
2103 
2120 void vpImageIo::readPNG(vpImage<unsigned char> &I, const std::string &filename)
2121 {
2122 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
2123  cv::Mat Ip = cv::imread(filename.c_str(), cv::IMREAD_GRAYSCALE);
2124  if (!Ip.empty())
2125  vpImageConvert::convert(Ip, I);
2126  else
2127  throw(vpImageException(vpImageException::ioError, "Can't read the image"));
2128 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020408)
2129  cv::Mat Ip = cv::imread(filename.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
2130  if (!Ip.empty())
2131  vpImageConvert::convert(Ip, I);
2132  else
2133  throw(vpImageException(vpImageException::ioError, "Can't read the image"));
2134 #else
2135  IplImage *Ip = NULL;
2136  Ip = cvLoadImage(filename.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
2137  if (Ip != NULL)
2138  vpImageConvert::convert(Ip, I);
2139  else
2140  throw(vpImageException(vpImageException::ioError, "Can't read the image"));
2141  cvReleaseImage(&Ip);
2142 #endif
2143 }
2144 
2163 void vpImageIo::readPNG(vpImage<vpRGBa> &I, const std::string &filename)
2164 {
2165 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
2166  cv::Mat Ip = cv::imread(filename.c_str(), cv::IMREAD_GRAYSCALE);
2167  if (!Ip.empty())
2168  vpImageConvert::convert(Ip, I);
2169  else
2170  throw(vpImageException(vpImageException::ioError, "Can't read the image"));
2171 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020408)
2172  cv::Mat Ip = cv::imread(filename.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
2173  if (!Ip.empty())
2174  vpImageConvert::convert(Ip, I);
2175  else
2176  throw(vpImageException(vpImageException::ioError, "Can't read the image"));
2177 #else
2178  IplImage *Ip = NULL;
2179  Ip = cvLoadImage(filename.c_str(), CV_LOAD_IMAGE_COLOR);
2180  if (Ip != NULL)
2181  vpImageConvert::convert(Ip, I);
2182  else
2183  throw(vpImageException(vpImageException::ioError, "Can't read the image"));
2184  cvReleaseImage(&Ip);
2185 #endif
2186 }
2187 #else
2188 void vpImageIo::readPNG(vpImage<unsigned char> &I, const std::string &filename)
2189 {
2190  int width = 0, height = 0, channels = 0;
2191  unsigned char *image = stbi_load(filename.c_str(), &width, &height, &channels, STBI_grey);
2192  if (image == NULL) {
2193  throw(vpImageException(vpImageException::ioError, "Can't read the image: %s", filename.c_str()));
2194  }
2195  I.init(image, static_cast<unsigned int>(height), static_cast<unsigned int>(width), true);
2196  stbi_image_free(image);
2197 }
2198 void vpImageIo::readPNG(vpImage<vpRGBa> &I, const std::string &filename)
2199 {
2200  int width = 0, height = 0, channels = 0;
2201  unsigned char *image = stbi_load(filename.c_str(), &width, &height, &channels, STBI_rgb_alpha);
2202  if (image == NULL) {
2203  throw(vpImageException(vpImageException::ioError, "Can't read the image: %s", filename.c_str()));
2204  }
2205  I.init(reinterpret_cast<vpRGBa*>(image), static_cast<unsigned int>(height), static_cast<unsigned int>(width), true);
2206  stbi_image_free(image);
2207 }
2208 void vpImageIo::writePNG(const vpImage<unsigned char> &I, const std::string &filename)
2209 {
2210  const int stride_in_bytes = static_cast<int>(I.getWidth());
2211  int res = stbi_write_png(filename.c_str(), static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight()), STBI_grey,
2212  reinterpret_cast<void*>(I.bitmap), stride_in_bytes);
2213  if (res == 0) {
2214  throw(vpImageException(vpImageException::ioError, "PNG write error: %s", filename.c_str()));
2215  }
2216 }
2217 void vpImageIo::writePNG(const vpImage<vpRGBa> &I, const std::string &filename)
2218 {
2219  const int stride_in_bytes = static_cast<int>(4 * I.getWidth());
2220  int res = stbi_write_png(filename.c_str(), static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight()), STBI_rgb_alpha,
2221  reinterpret_cast<void*>(I.bitmap), stride_in_bytes);
2222  if (res == 0) {
2223  throw(vpImageException(vpImageException::ioError, "PNG write error: %s", filename.c_str()));
2224  }
2225 }
2226 #endif
static void writeJPEG(const vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:1055
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:97
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
void init(unsigned int height, unsigned int width)
Set the size of the image.
Definition: vpImage.h:667
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:881
#define vpCERROR
Definition: vpDebug.h:365
unsigned char B
Blue component.
Definition: vpRGBa.h:150
Type * bitmap
points toward the bitmap
Definition: vpImage.h:143
#define vpERROR_TRACE
Definition: vpDebug.h:393
error that can be emited by ViSP classes.
Definition: vpException.h:71
Error that can be emited by the vpImage class and its derivates.
unsigned char G
Green component.
Definition: vpRGBa.h:149
static std::string path(const std::string &pathname)
Definition: vpIoTools.cpp:841
static void writePPM(const vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:987
Definition: vpRGBa.h:66
static void write(const vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:445
static void readPPM(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:908
static void writePFM(const vpImage< float > &I, const std::string &filename)
Definition: vpImageIo.cpp:602
static std::vector< std::string > splitChain(const std::string &chain, const std::string &sep)
Definition: vpIoTools.cpp:1677
static void readPFM(vpImage< float > &I, const std::string &filename)
Definition: vpImageIo.cpp:768
unsigned int getHeight() const
Definition: vpImage.h:188
static void read(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:243
unsigned int getSize() const
Definition: vpImage.h:227
static void readPNG(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:1720
unsigned char R
Red component.
Definition: vpRGBa.h:148
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:640
static void readPGM(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:822
unsigned int getWidth() const
Definition: vpImage.h:246
static void writePGM(const vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:648
static void readJPEG(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:1183
static void writePNG(const vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:1511