YARP
Yet Another Robot Platform
ImageFile.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  * Copyright (C) 2006-2010 RobotCub Consortium
4  * All rights reserved.
5  *
6  * This software may be modified and distributed under the terms of the
7  * BSD-3-Clause license. See the accompanying LICENSE file for details.
8  */
9 
10 #include <yarp/sig/ImageFile.h>
11 #include <yarp/os/LogComponent.h>
12 #include <yarp/os/LogStream.h>
13 
14 #include <cstdio>
15 #include <cstring>
16 #include <cstdlib>
17 
18 #if YARP_HAS_JPEG_C
19 #include "jpeglib.h"
20 #endif
21 
22 #if defined (YARP_HAS_PNG)
23 #include <png.h>
24 #endif
25 
26 #if defined (YARP_HAS_ZLIB)
27 #include <zlib.h>
28 #endif
29 
30 using namespace std;
31 using namespace yarp::os;
32 using namespace yarp::sig;
33 
34 namespace
35 {
36  YARP_LOG_COMPONENT(IMAGEFILE, "yarp.sig.ImageFile")
37 }
38 
39 namespace
40 {
41  bool ImageReadRGB_PNG(ImageOf<PixelRgb>& img, const char* filename);
42  bool ImageReadBGR_PNG(ImageOf<PixelBgr>& img, const char* filename);
43  bool ImageReadMono_PNG(ImageOf<PixelMono>& img, const char* filename);
44 
45  bool ReadHeader_PxM(FILE* fp, int* height, int* width, int* color);
46  bool ImageReadMono_PxM(ImageOf<PixelMono>& img, const char* filename);
47  bool ImageReadRGB_PxM(ImageOf<PixelRgb>& img, const char* filename);
48  bool ImageReadBGR_PxM(ImageOf<PixelBgr>& img, const char* filename);
49 
50  bool ImageReadFloat_PlainHeaderless(ImageOf<PixelFloat>& dest, const std::string& filename);
51 #if defined (YARP_HAS_ZLIB)
52  bool ImageReadFloat_CompressedHeaderless(ImageOf<PixelFloat>& dest, const std::string& filename);
53 #endif
54 
55  bool SaveJPG(char* src, const char* filename, size_t h, size_t w, size_t rowSize);
56  bool SavePGM(char* src, const char* filename, size_t h, size_t w, size_t rowSize);
57  bool SavePPM(char* src, const char* filename, size_t h, size_t w, size_t rowSize);
58 #if defined (YARP_HAS_PNG)
59  bool SavePNG(char* src, const char* filename, size_t h, size_t w, size_t rowSize, png_byte color_type, png_byte bit_depth);
60 #endif
61  bool SaveFloatRaw(char* src, const char* filename, size_t h, size_t w, size_t rowSize);
62 #if defined (YARP_HAS_ZLIB)
63  bool SaveFloatCompressed(char* src, const char* filename, size_t h, size_t w, size_t rowSize);
64 #endif
65 
66  bool ImageWriteJPG(ImageOf<PixelRgb>& img, const char* filename);
67  bool ImageWritePNG(ImageOf<PixelRgb>& img, const char* filename);
68  bool ImageWritePNG(ImageOf<PixelMono>& img, const char* filename);
69  bool ImageWriteRGB(ImageOf<PixelRgb>& img, const char* filename);
70  bool ImageWriteMono(ImageOf<PixelMono>& img, const char* filename);
71 
72  bool ImageWriteFloat_PlainHeaderless(ImageOf<PixelFloat>& img, const char* filename);
73  bool ImageWriteFloat_CompressedHeaderless(ImageOf<PixelFloat>& img, const char* filename);
74 };
75 
77 // private read methods for PNG Files
79 namespace {
80 bool ImageReadRGB_PNG(ImageOf<PixelRgb>& img, const char* filename)
81 {
82 #if defined (YARP_HAS_PNG)
83  FILE* fp = fopen(filename, "rb");
84 
85  png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
86  if (!png)
87  {
88  yCError(IMAGEFILE) << "PNG internal error";
89  return false;
90  }
91 
92  png_infop info = png_create_info_struct(png);
93  if (!info)
94  {
95  yCError(IMAGEFILE) << "PNG internal error";
96  return false;
97  }
98 
99  if (setjmp(png_jmpbuf(png)))
100  {
101  yCError(IMAGEFILE) << "PNG internal error";
102  return false;
103  }
104 
105  png_init_io(png, fp);
106 
107  png_read_info(png, info);
108 
109  int width = png_get_image_width(png, info);
110  int height = png_get_image_height(png, info);
111  png_byte color_type = png_get_color_type(png, info);
112  png_byte bit_depth = png_get_bit_depth(png, info);
113 
114  // Read any color_type into 8bit depth, RGBA format.
115  // See http://www.libpng.org/pub/png/libpng-manual.txt
116 
117  if (bit_depth == 16)
118  png_set_strip_16(png);
119 
120  if (color_type == PNG_COLOR_TYPE_PALETTE)
121  png_set_palette_to_rgb(png);
122 
123  // PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth.
124  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
125  png_set_expand_gray_1_2_4_to_8(png);
126 
127  if (png_get_valid(png, info, PNG_INFO_tRNS))
128  png_set_tRNS_to_alpha(png);
129 
130  // These color_type don't have an alpha channel then fill it with 0xff.
131  if (color_type == PNG_COLOR_TYPE_RGB ||
132  color_type == PNG_COLOR_TYPE_GRAY ||
133  color_type == PNG_COLOR_TYPE_PALETTE)
134  png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
135 
136  if (color_type == PNG_COLOR_TYPE_GRAY ||
137  color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
138  png_set_gray_to_rgb(png);
139 
140  png_read_update_info(png, info);
141 
142  png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height);
143  for (int y = 0; y < height; y++)
144  {
145  row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png, info));
146  }
147 
148  png_read_image(png, row_pointers);
149  fclose(fp);
150 
151  img.resize(width,height);
152  for (int y = 0; y < height; y++)
153  {
154  png_bytep row = row_pointers[y];
155  for (int x = 0; x < width; x++)
156  {
157  png_bytep px = &(row[x * 4]);
158  unsigned char* address = img.getPixelAddress(x,y);
159  address[0] = px[0];
160  address[1] = px[1];
161  address[2] = px[2];
162  }
163  }
164 
165  png_destroy_read_struct(&png, &info, NULL);
166  for (int y = 0; y < height; y++)
167  {
168  free(row_pointers[y]);
169  }
170  free(row_pointers);
171  return true;
172 #else
173  yCError(IMAGEFILE) << "PNG library not available/not found";
174  return false;
175 #endif
176 }
177 
178 bool ImageReadBGR_PNG(ImageOf<PixelBgr>& img, const char* filename)
179 {
180 #if defined (YARP_HAS_PNG)
181  yCError(IMAGEFILE) << "Not yet implemented";
182  return false;
183 #else
184  yCError(IMAGEFILE) << "PNG library not available/not found";
185  return false;
186 #endif
187 }
188 
189 bool ImageReadMono_PNG(ImageOf<PixelMono>& img, const char* filename)
190 {
191 #if defined (YARP_HAS_PNG)
192  yCError(IMAGEFILE) << "Not yet implemented";
193  return false;
194 #else
195  yCError(IMAGEFILE) << "PNG library not available/not found";
196  return false;
197 #endif
198 }
199 
201 // private read methods for PGM/PPM Files
203 
204 bool ReadHeader_PxM(FILE *fp, int *height, int *width, int *color)
205 {
206  char ch;
207  int maxval;
208 
209  *color = 0;
210 
212  if (fscanf(fp, "P%c\n", &ch) != 1 || (ch!='6'&&ch!='5'))
213  {
214  yCWarning(IMAGEFILE, "file is not in pgm/ppm raw format; cannot read");
215  return false;
216  }
217 
218  if (ch=='6') *color = 1;
219 
220  // skip comments
221  ch = fgetc(fp);
222  while (ch == '#')
223  {
224  do
225  {
226  ch = fgetc(fp);
227  }
228  while (ch != '\n');
229  ch = fgetc(fp);
230  }
231  ungetc(ch, fp);
232 
234  int n=fscanf(fp, "%d%d%d", width, height, &maxval);
235  if (n!=3)
236  return false;
237 
238  fgetc(fp);
239  if (maxval != 255)
240  {
241  //die("image is not true-color (24 bit); read failed");
242  yCWarning(IMAGEFILE, "image is not true-color (24 bit); read failed");
243  return false;
244  }
245 
246  return true;
247 }
248 
249 
250 bool ImageReadRGB_PxM(ImageOf<PixelRgb> &img, const char *filename)
251 {
252  int width, height, color, num;
253  FILE *fp=nullptr;
254  fp = fopen(filename, "rb");
255 
256  if(fp==nullptr)
257  {
258  yCError(IMAGEFILE, "Error opening %s, check if file exists.\n", filename);
259  return false;
260  }
261 
262  if (!ReadHeader_PxM(fp, &height, &width, &color))
263  {
264  fclose (fp);
265  yCError(IMAGEFILE, "Error reading header, is file a valid ppm/pgm?\n");
266  return false;
267  }
268 
269  if (!color)
270  {
271  ImageOf<PixelMono> tmp;
272  tmp.resize(width,height);
273 
274  const int w = tmp.width() * tmp.getPixelSize();
275  const int h = tmp.height();
276  const int pad = tmp.getRowSize();
277  unsigned char *dst = tmp.getRawImage ();
278 
279  num = 0;
280  for (int i = 0; i < h; i++)
281  {
282  num += (int)fread((void *) dst, 1, (size_t) w, fp);
283  dst += pad;
284  }
285  fclose(fp);
286  img.copy(tmp);
287  return true;
288  }
289 
290  img.resize(width,height);
291 
292  const int w = img.width() * img.getPixelSize();
293  const int h = img.height();
294  const int pad = img.getRowSize();
295  unsigned char *dst = img.getRawImage ();
296 
297  num = 0;
298  for (int i = 0; i < h; i++)
299  {
300  num += (int)fread((void *) dst, 1, (size_t) w, fp);
301  dst += pad;
302  }
303 
304  fclose(fp);
305 
306  return true;
307 }
308 
309 #if defined (YARP_HAS_ZLIB)
310 bool ImageReadFloat_CompressedHeaderless(ImageOf<PixelFloat>& dest, const std::string& filename)
311 {
312  FILE* fp = fopen(filename.c_str(), "rb");
313  if (fp == nullptr) {
314  return false;
315  }
316 
317  size_t br = 0;
318 
319  //get the file size
320  fseek(fp, 0, SEEK_END);
321  size_t sizeDataCompressed = ftell(fp);
322  rewind(fp);
323 
324  //read the compressed data
325  char* dataReadInCompressed = new char[sizeDataCompressed];
326  br = fread(dataReadInCompressed, 1, sizeDataCompressed, fp);
327  fclose(fp);
328 
329  if (br != sizeDataCompressed) { yError() << "problems reading file!"; delete [] dataReadInCompressed; return false; }
330 
331  size_t h = ((size_t*)(dataReadInCompressed))[0]; //byte 0
332  size_t w = ((size_t*)(dataReadInCompressed))[1]; //byte 8, because size_t is 8 bytes long
333  size_t hds = 2* sizeof(size_t); //16 bytes
334 
335  dest.resize(w, h);
336  unsigned char* destbuff = dest.getRawImage();
337  //this is the size of the image
338  size_t sizeDataUncompressed = dest.getRawImageSize();
339  //this is the size of the buffer. Extra space is required for temporary operations (I choose arbitrarily *2)
340  size_t sizeDataUncompressedExtra = sizeDataUncompressed*2;
341 
342  char* dataUncompressed = new char[sizeDataUncompressedExtra];
343 
344  int z_result = uncompress((Bytef*) dataUncompressed, (uLongf*)&sizeDataUncompressedExtra, (const Bytef*)dataReadInCompressed+ hds, sizeDataCompressed- hds);
345  switch (z_result)
346  {
347  case Z_OK:
348  break;
349 
350  case Z_MEM_ERROR:
351  yCError(IMAGEFILE, "zlib compression: out of memory");
352  delete[] dataUncompressed;
353  return false;
354  break;
355 
356  case Z_BUF_ERROR:
357  yCError(IMAGEFILE, "zlib compression: output buffer wasn't large enough");
358  delete[] dataUncompressed;
359  return false;
360  break;
361 
362  case Z_DATA_ERROR:
363  yCError(IMAGEFILE, "zlib compression: file contains corrupted data");
364  delete[] dataUncompressed;
365  return false;
366  break;
367  }
368 
369  //here I am copy only the size of the image, obviously the extra space is not needed anymore.
370  for (size_t i=0; i< sizeDataUncompressed; i++)
371  {
372  destbuff[i] = dataUncompressed[i];
373  }
374 
375  delete [] dataUncompressed;
376  return true;
377 }
378 #endif
379 
380 bool ImageReadFloat_PlainHeaderless(ImageOf<PixelFloat>& dest, const std::string& filename)
381 {
382  FILE *fp = fopen(filename.c_str(), "rb");
383  if (fp == nullptr) {
384  return false;
385  }
386 
387  size_t dims[2];
388  if (fread(dims, sizeof(dims), 1, fp) == 0)
389  {
390  fclose(fp);
391  return false;
392  }
393 
394  size_t h = dims[0];
395  size_t w = dims[1];
396  dest.resize(w, h);
397  size_t pad = dest.getRowSize();
398  size_t bytes_to_read_per_row = w* dest.getPixelSize();
399  unsigned char* dst = dest.getRawImage();
400  size_t num = 0;
401  for (size_t i = 0; i < h; i++)
402  {
403  num += (int)fread((void*)dst, 1, bytes_to_read_per_row, fp);
404  dst += pad;
405  }
406 
407  fclose(fp);
408  return (num > 0);
409 }
410 
411 bool ImageReadBGR_PxM(ImageOf<PixelBgr> &img, const char *filename)
412 {
413  int width, height, color, num;
414  FILE *fp=nullptr;
415  fp = fopen(filename, "rb");
416 
417  if(fp==nullptr)
418  {
419  yCError(IMAGEFILE, "Error opening %s, check if file exists.\n", filename);
420  return false;
421  }
422 
423  if (!ReadHeader_PxM(fp, &height, &width, &color))
424  {
425  fclose (fp);
426  yCError(IMAGEFILE, "Error reading header, is file a valid ppm/pgm?\n");
427  return false;
428  }
429 
430  if (!color)
431  {
432  fclose(fp);
433  yCError(IMAGEFILE, "File is grayscale, conversion not yet supported\n");
434  return false;
435  }
436 
437  ImageOf<PixelRgb> tmpImg;
438  tmpImg.resize(width, height);
439 
440  const int w = tmpImg.width() * img.getPixelSize();
441  const int h = tmpImg.height();
442  const int pad = tmpImg.getRowSize();
443  unsigned char *dst = tmpImg.getRawImage ();
444 
445  num = 0;
446  for (int i = 0; i < h; i++)
447  {
448  num += (int)fread((void *) dst, 1, (size_t) w, fp);
449  dst += pad;
450  }
451 
452  fclose(fp);
453 
454  return img.copy(tmpImg);
455 }
456 
457 
458 bool ImageReadMono_PxM(ImageOf<PixelMono> &img, const char *filename)
459 {
460  int width, height, color, num;
461  FILE *fp=nullptr;
462  fp = fopen(filename, "rb");
463 
464  if(fp==nullptr)
465  {
466  yCError(IMAGEFILE, "Error opening %s, check if file exists.\n", filename);
467  return false;
468  }
469 
470  if (!ReadHeader_PxM(fp, &height, &width, &color))
471  {
472  fclose (fp);
473  yCError(IMAGEFILE, "Error reading header, is file a valid ppm/pgm?\n");
474  return false;
475  }
476 
477  if (color)
478  {
479  fclose(fp);
480  yCError(IMAGEFILE, "File is color, conversion not yet supported\n");
481  return false;
482  }
483 
484  img.resize(width,height);
485 
486  const int w = img.width() * img.getPixelSize();
487  const int h = img.height();
488  const int pad = img.getRowSize();
489  unsigned char *dst = img.getRawImage ();
490 
491  num = 0;
492  for (int i = 0; i < h; i++)
493  {
494  num += (int)fread((void *) dst, 1, (size_t) w, fp);
495  dst += pad;
496  }
497 
498  fclose(fp);
499 
500  return true;
501 }
502 
504 // private write methods
506 
507 #if defined (YARP_HAS_PNG)
508 bool SavePNG(char *src, const char *filename, size_t h, size_t w, size_t rowSize, png_byte color_type, png_byte bit_depth)
509 {
510  // create file
511  if (src == nullptr)
512  {
513  yCError(IMAGEFILE, "[write_png_file] Cannot write to file a nullptr image");
514  return false;
515  }
516 
517  if (filename == nullptr)
518  {
519  yCError(IMAGEFILE, "[write_png_file] Filename is nullptr");
520  return false;
521  }
522 
523  FILE *fp = fopen(filename, "wb");
524  if (!fp)
525  {
526  yCError(IMAGEFILE, "[write_png_file] File %s could not be opened for writing", filename);
527  return false;
528  }
529 
530  // initialize stuff
531  png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
532  if (!png_ptr)
533  {
534  yCError(IMAGEFILE, "[write_png_file] png_create_write_struct failed");
535  fclose(fp);
536  return false;
537  }
538 
539  png_infop info_ptr = png_create_info_struct(png_ptr);
540  if (!info_ptr)
541  {
542  yCError(IMAGEFILE, "[write_png_file] png_create_info_struct failed");
543  fclose(fp);
544  return false;
545  }
546 
547  //init io
548  if (setjmp(png_jmpbuf(png_ptr)))
549  {
550  yCError(IMAGEFILE, "[write_png_file] Error during init_io");
551  fclose(fp);
552  return false;
553  }
554  png_init_io(png_ptr, fp);
555 
556  // write header
557  if (setjmp(png_jmpbuf(png_ptr)))
558  {
559  yCError(IMAGEFILE, "[write_png_file] Error during writing header");
560  fclose(fp);
561  return false;
562  }
563  png_set_IHDR(png_ptr, info_ptr, w, h,
564  bit_depth, color_type, PNG_INTERLACE_NONE,
565  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
566 
567  //write info
568  png_write_info(png_ptr, info_ptr);
569 
570  //allocate data space
571  png_bytep* row_pointers = new png_bytep[h];
572 
573  for (size_t y = 0; y < h; y++)
574  {
575  //this is an array of pointers. Each element points to a row of the image
576  row_pointers[y] = (png_bytep)(src) + (y * rowSize);
577  }
578 
579  // write bytes
580  if (setjmp(png_jmpbuf(png_ptr)))
581  {
582  yCError(IMAGEFILE, "[write_png_file] Error during writing bytes");
583  delete [] row_pointers;
584  png_destroy_write_struct(&png_ptr, &info_ptr);
585  fclose(fp);
586  return false;
587  }
588  png_write_image(png_ptr, row_pointers);
589 
590  // end write
591  if (setjmp(png_jmpbuf(png_ptr)))
592  {
593  yCError(IMAGEFILE, "[write_png_file] Error during end of write");
594  delete [] row_pointers;
595  png_destroy_write_struct(&png_ptr, &info_ptr);
596  fclose(fp);
597  return false;
598  }
599  png_write_end(png_ptr, info_ptr);
600 
601  // finished. cleanup allocation
602  delete[] row_pointers;
603  png_destroy_write_struct(&png_ptr, &info_ptr);
604  fclose(fp);
605  return true;
606 }
607 #endif
608 
609 bool SaveJPG(char *src, const char *filename, size_t h, size_t w, size_t rowSize)
610 {
611 #if YARP_HAS_JPEG_C
612  int quality = 100;
613  struct jpeg_compress_struct cinfo;
614  struct jpeg_error_mgr jerr;
615  FILE * outfile = nullptr;
616  JSAMPROW row_pointer[1];
617  int row_stride;
618 
619  cinfo.err = jpeg_std_error(&jerr);
620  jpeg_create_compress(&cinfo);
621 
622  if ((outfile = fopen(filename, "wb")) == nullptr)
623  {
624  yCError(IMAGEFILE, "can't write file: %s\n", filename);
625  return false;
626  }
627  jpeg_stdio_dest(&cinfo, outfile);
628 
629  cinfo.image_width = w;
630  cinfo.image_height = h;
631  cinfo.input_components = 3;
632  cinfo.in_color_space = JCS_RGB;
633  jpeg_set_defaults(&cinfo);
634  jpeg_set_quality(&cinfo, quality, TRUE);
635 
636  jpeg_start_compress(&cinfo, TRUE);
637 
638  row_stride = w * 3;
639 
640  while (cinfo.next_scanline < cinfo.image_height)
641  {
642  row_pointer[0] = (JSAMPROW)&src[cinfo.next_scanline * row_stride];
643  (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
644  }
645 
646  jpeg_finish_compress(&cinfo);
647  fclose(outfile);
648  jpeg_destroy_compress(&cinfo);
649  return true;
650 #else
651  yCError(IMAGEFILE) << "libjpeg not installed";
652  return false;
653 #endif
654 }
655 
656 bool SavePGM(char *src, const char *filename, size_t h, size_t w, size_t rowSize)
657 {
658  FILE *fp = fopen(filename, "wb");
659  if (!fp)
660  {
661  yCError(IMAGEFILE, "cannot open file %s for writing\n", filename);
662  return false;
663  }
664  else
665  {
666  const int inc = rowSize;
667 
668  fprintf(fp, "P5\n%zu %zu\n%d\n", w, h, 255);
669  for (size_t i = 0; i < h; i++)
670  {
671  fwrite((void *)src, 1, (size_t)w, fp);
672  src += inc;
673  }
674 
675  fclose(fp);
676  }
677 
678  return true;
679 }
680 
681 
682 bool SavePPM(char *src, const char *filename, size_t h, size_t w, size_t rowSize)
683 {
684  FILE *fp = fopen(filename, "wb");
685  if (!fp)
686  {
687  yCError(IMAGEFILE, "cannot open file %s for writing\n", filename);
688  return false;
689  }
690  else
691  {
692  const int inc = rowSize;//YARPSimpleOperation::ComputePadding (w*3, YarpImageAlign) + w * 3;
693 
694  fprintf(fp, "P6\n%zu %zu\n%d\n", w, h, 255);
695  for (size_t i = 0; i < h; i++)
696  {
697  fwrite((void *)src, 1, (size_t)(w * 3), fp);
698  src += inc;
699  }
700 
702  fclose(fp);
703  }
704 
705  return true;
706 }
707 
708 #if defined (YARP_HAS_ZLIB)
709 bool SaveFloatCompressed(char* src, const char* filename, size_t h, size_t w, size_t rowSize)
710 {
711  size_t sizeDataOriginal=w*h*sizeof(float);
712  size_t sizeDataCompressed = (sizeDataOriginal * 1.1) + 12;
713  char* dataCompressed = (char*)malloc(sizeDataCompressed);
714 
715  int z_result = compress((Bytef*) dataCompressed,(uLongf*) &sizeDataCompressed, (Bytef*)src, sizeDataOriginal);
716  switch (z_result)
717  {
718  case Z_OK:
719  break;
720 
721  case Z_MEM_ERROR:
722  yCError(IMAGEFILE, "zlib compression: out of memory");
723  return false;
724  break;
725 
726  case Z_BUF_ERROR:
727  yCError(IMAGEFILE, "zlib compression: output buffer wasn't large enough");
728  return false;
729  break;
730  }
731 
732  FILE* fp = fopen(filename, "wb");
733  if (fp == nullptr)
734  {
735  return false;
736  }
737 
738  size_t bw = 0;
739  size_t dims[2] = { h,w };
740 
741  if (fwrite(dims, sizeof(dims), 1, fp) > 0) {
742  bw = fwrite((void*)dataCompressed, sizeDataCompressed, 1, fp);
743  }
744 
745  fclose(fp);
746  return (bw > 0);
747 }
748 #endif
749 
750 bool SaveFloatRaw(char* src, const char* filename, size_t h, size_t w, size_t rowSize)
751 {
752  FILE* fp = fopen(filename, "wb");
753  if (fp == nullptr)
754  {
755  return false;
756  }
757 
758  size_t dims[2] = { h,w };
759 
760  size_t bw = 0;
761  size_t size_ = sizeof(float);
762  auto count_ = (size_t)(dims[0] * dims[1]);
763 
764  if (fwrite(dims, sizeof(dims), 1, fp) > 0) {
765  bw = fwrite((void*)src, size_, count_, fp);
766  }
767 
768  fclose(fp);
769  return (bw > 0);
770 }
771 
772 bool ImageWriteJPG(ImageOf<PixelRgb>& img, const char *filename)
773 {
774  return SaveJPG((char*)img.getRawImage(), filename, img.height(), img.width(), img.getRowSize());
775 }
776 
777 bool ImageWritePNG(ImageOf<PixelRgb>& img, const char *filename)
778 {
779 #if defined (YARP_HAS_PNG)
780  return SavePNG((char*)img.getRawImage(), filename, img.height(), img.width(), img.getRowSize(), PNG_COLOR_TYPE_RGB, 8);
781 #else
782  yCError(IMAGEFILE) << "YARP was not built with png support";
783  return false;
784 #endif
785 }
786 
787 bool ImageWritePNG(ImageOf<PixelMono>& img, const char *filename)
788 {
789 #if defined (YARP_HAS_PNG)
790  return SavePNG((char*)img.getRawImage(), filename, img.height(), img.width(), img.getRowSize(), PNG_COLOR_TYPE_GRAY, 8);
791 #else
792  yCError(IMAGEFILE) << "YARP was not built with png support";
793  return false;
794 #endif
795 }
796 
797 bool ImageWriteRGB(ImageOf<PixelRgb>& img, const char *filename)
798 {
799  return SavePPM((char*)img.getRawImage(),filename,img.height(),img.width(),img.getRowSize());
800 }
801 
802 bool ImageWriteMono(ImageOf<PixelMono>& img, const char *filename)
803 {
804  return SavePGM((char*)img.getRawImage(), filename, img.height(), img.width(), img.getRowSize());
805 }
806 
807 bool ImageWriteFloat_PlainHeaderless(ImageOf<PixelFloat>& img, const char *filename)
808 {
809  return SaveFloatRaw((char*)img.getRawImage(), filename, img.height(), img.width(), img.getRowSize());
810 }
811 
812 bool ImageWriteFloat_CompressedHeaderless(ImageOf<PixelFloat>& img, const char* filename)
813 {
814 #if defined (YARP_HAS_ZLIB)
815  return SaveFloatCompressed((char*)img.getRawImage(), filename, img.height(), img.width(), img.getRowSize());
816 #else
817  yCError(IMAGEFILE) << "YARP was not built with zlib support";
818  return false;
819 #endif
820 }
821 }
822 
824 // public read methods
826 
827 bool file::read(ImageOf<PixelRgb> & dest, const std::string& src, image_fileformat format)
828 {
829  const char* file_ext = strrchr(src.c_str(), '.');
830  if (strcmp(file_ext, ".pgm")==0 ||
831  strcmp(file_ext, ".ppm")==0 ||
832  format == FORMAT_PGM ||
833  format == FORMAT_PPM)
834  {
835  return ImageReadRGB_PxM(dest,src.c_str());
836  }
837  else if(strcmp(file_ext, ".png")==0 ||
838  format == FORMAT_PNG)
839  {
840  return ImageReadRGB_PNG(dest, src.c_str());
841  }
842  else if(strcmp(file_ext, ".jpg") == 0 ||
843  strcmp(file_ext, ".jpeg") == 0 ||
844  format == FORMAT_JPG)
845  {
846  yCError(IMAGEFILE) << "jpeg not yet implemented";
847  return false;
848  }
849  yCError(IMAGEFILE) << "unsupported file format";
850  return false;
851 }
852 
853 
854 bool file::read(ImageOf<PixelBgr> & dest, const std::string& src, image_fileformat format)
855 {
856  const char* file_ext = strrchr(src.c_str(), '.');
857  if (strcmp(file_ext, ".pgm") == 0 ||
858  strcmp(file_ext, ".ppm") == 0 ||
859  format == FORMAT_PGM ||
860  format == FORMAT_PPM)
861  {
862  return ImageReadBGR_PxM(dest, src.c_str());
863  }
864  else if (strcmp(file_ext, ".png") == 0 ||
865  format == FORMAT_PNG)
866  {
867  return ImageReadBGR_PNG(dest, src.c_str());
868  }
869  else if (strcmp(file_ext, ".jpg") == 0 ||
870  strcmp(file_ext, ".jpeg") == 0 ||
871  format == FORMAT_JPG)
872  {
873  yCError(IMAGEFILE) << "jpeg not yet implemented";
874  return false;
875  }
876  yCError(IMAGEFILE) << "unsupported file format";
877  return false;
878 }
879 
880 
881 bool file::read(ImageOf<PixelRgba> & dest, const std::string& src, image_fileformat format)
882 {
883  const char* file_ext = strrchr(src.c_str(), '.');
884  if (strcmp(file_ext, ".pgm") == 0 ||
885  strcmp(file_ext, ".ppm") == 0 ||
886  format == FORMAT_PGM ||
887  format == FORMAT_PPM)
888  {
889  ImageOf<PixelRgb> img2;
890  bool ok = ImageReadRGB_PxM(img2, src.c_str());
891  if (ok)
892  {
893  dest.copy(img2);
894  }
895  return ok;
896  }
897  else if (strcmp(file_ext, ".png") == 0 ||
898  format == FORMAT_PNG)
899  {
900  ImageOf<PixelRgb> img2;
901  bool ok = ImageReadRGB_PNG(img2, src.c_str());
902  if (ok)
903  {
904  dest.copy(img2);
905  }
906  return ok;
907  }
908  else if (strcmp(file_ext, ".jpg") == 0 ||
909  strcmp(file_ext, ".jpeg") == 0 ||
910  format == FORMAT_JPG)
911  {
912  yCError(IMAGEFILE) << "jpeg not yet implemented";
913  return false;
914  }
915  yCError(IMAGEFILE) << "unsupported file format";
916  return false;
917 }
918 
919 bool file::read(ImageOf<PixelMono> & dest, const std::string& src, image_fileformat format)
920 {
921  const char* file_ext = strrchr(src.c_str(), '.');
922  if (strcmp(file_ext, ".pgm") == 0 ||
923  strcmp(file_ext, ".ppm") == 0 ||
924  format == FORMAT_PGM ||
925  format == FORMAT_PPM)
926  {
927  return ImageReadMono_PxM(dest, src.c_str());
928  }
929  else if (strcmp(file_ext, ".png") == 0 ||
930  format == FORMAT_PNG)
931  {
932  return ImageReadMono_PNG(dest, src.c_str());
933  }
934  else if (strcmp(file_ext, ".jpg") == 0 ||
935  strcmp(file_ext, ".jpeg") == 0 ||
936  format == FORMAT_JPG)
937  {
938  yCError(IMAGEFILE) << "jpeg not yet implemented";
939  return false;
940  }
941  yCError(IMAGEFILE) << "unsupported file format";
942  return false;
943 }
944 
945 bool file::read(ImageOf<PixelFloat>& dest, const std::string& src, image_fileformat format)
946 {
947  const char* file_ext = strrchr(src.c_str(), '.');
948  if (strcmp(file_ext, ".float") == 0 ||
949  format == FORMAT_NUMERIC)
950  {
951  return ImageReadFloat_PlainHeaderless(dest, src);
952  }
953  else if (strcmp(file_ext, ".floatzip") == 0 ||
954  format == FORMAT_NUMERIC_COMPRESSED)
955  {
956 #if defined (YARP_HAS_ZLIB)
957  return ImageReadFloat_CompressedHeaderless(dest, src);
958 #else
959  yCError(IMAGEFILE) << "YARP was not built with zlib support";
960  return false;
961 #endif
962  }
963  yCError(IMAGEFILE) << "unsupported file format";
964  return false;
965 }
966 
970 
971 bool file::write(const ImageOf<PixelRgb> & src, const std::string& dest, image_fileformat format)
972 {
973  if (format == FORMAT_PPM)
974  {
975  return ImageWriteRGB(const_cast<ImageOf<PixelRgb> &>(src), dest.c_str());
976  }
977  else if (format == FORMAT_JPG)
978  {
979  return ImageWriteJPG(const_cast<ImageOf<PixelRgb> &>(src), dest.c_str());
980  }
981  else if (format == FORMAT_PNG)
982  {
983  return ImageWritePNG(const_cast<ImageOf<PixelRgb> &>(src), dest.c_str());
984  }
985  else
986  {
987  yCError(IMAGEFILE) << "Invalid format, operation not supported";
988  return false;
989  }
990 }
991 
992 bool file::write(const ImageOf<PixelBgr> & src, const std::string& dest, image_fileformat format)
993 {
994  ImageOf<PixelRgb> imgRGB;
995  imgRGB.copy(src);
996  if (format == FORMAT_PPM)
997  {
998  return ImageWriteRGB(const_cast<ImageOf<PixelRgb> &>(imgRGB), dest.c_str());
999  }
1000  else if (format == FORMAT_JPG)
1001  {
1002  return ImageWriteJPG(const_cast<ImageOf<PixelRgb> &>(imgRGB), dest.c_str());
1003  }
1004  else if (format == FORMAT_PNG)
1005  {
1006  return ImageWritePNG(const_cast<ImageOf<PixelRgb> &>(imgRGB), dest.c_str());
1007  }
1008  else
1009  {
1010  yCError(IMAGEFILE) << "Invalid format, operation not supported";
1011  return false;
1012  }
1013 }
1014 
1015 
1016 bool file::write(const ImageOf<PixelRgba> & src, const std::string& dest, image_fileformat format)
1017 {
1018  ImageOf<PixelRgb> imgRGB;
1019  imgRGB.copy(src);
1020  if (format == FORMAT_PPM)
1021  {
1022  return ImageWriteRGB(const_cast<ImageOf<PixelRgb> &>(imgRGB), dest.c_str());
1023  }
1024  else if (format == FORMAT_JPG)
1025  {
1026  return ImageWriteJPG(const_cast<ImageOf<PixelRgb> &>(imgRGB), dest.c_str());
1027  }
1028  else if (format == FORMAT_PNG)
1029  {
1030  return ImageWritePNG(const_cast<ImageOf<PixelRgb> &>(imgRGB), dest.c_str());
1031  }
1032  else
1033  {
1034  yCError(IMAGEFILE) << "Invalid format, operation not supported";
1035  return false;
1036  }
1037 }
1038 
1039 
1040 bool file::write(const ImageOf<PixelMono> & src, const std::string& dest, image_fileformat format)
1041 {
1042  if (format == FORMAT_PGM)
1043  {
1044  return ImageWriteMono(const_cast<ImageOf<PixelMono> &>(src), dest.c_str());
1045  }
1046  else if (format == FORMAT_PNG)
1047  {
1048  return ImageWritePNG(const_cast<ImageOf<PixelMono> &>(src), dest.c_str());
1049  }
1050  else
1051  {
1052  yCError(IMAGEFILE) << "Invalid format, operation not supported";
1053  return false;
1054  }
1055 }
1056 
1057 bool file::write(const ImageOf<PixelFloat>& src, const std::string& dest, image_fileformat format)
1058 {
1059  if (format == FORMAT_NUMERIC)
1060  {
1061  return ImageWriteFloat_PlainHeaderless(const_cast<ImageOf<PixelFloat> &>(src), dest.c_str());
1062  }
1063  else if (format == FORMAT_NUMERIC_COMPRESSED)
1064  {
1065  return ImageWriteFloat_CompressedHeaderless(const_cast<ImageOf<PixelFloat>&>(src), dest.c_str());
1066  }
1067  else
1068  {
1069  yCError(IMAGEFILE) << "Invalid format, operation not supported";
1070  return false;
1071  }
1072 }
1073 
1074 bool file::write(const Image& src, const std::string& dest, image_fileformat format)
1075 {
1076  int code=src.getPixelCode();
1077  if (code == VOCAB_PIXEL_MONO)
1078  {
1079  return write(static_cast<const ImageOf<PixelMono>&>(src), dest, format);
1080  }
1081  else if (code == VOCAB_PIXEL_MONO_FLOAT)
1082  {
1083  return write(static_cast<const ImageOf<PixelFloat>&>(src), dest, format);
1084  }
1085  else if (code == VOCAB_PIXEL_BGR)
1086  {
1087  return write(static_cast<const ImageOf<PixelBgr>&>(src), dest, format);
1088  }
1089  else if (code == VOCAB_PIXEL_RGB)
1090  {
1091  return write(static_cast<const ImageOf<PixelRgb>&>(src), dest, format);
1092  }
1093  else if (code == VOCAB_PIXEL_RGBA)
1094  {
1095  return write(static_cast<const ImageOf<PixelRgba>&>(src), dest, format);
1096  }
1097  else
1098  {
1099  ImageOf<PixelRgb> img;
1100  img.copy(src);
1101  return write(img,dest);
1102  }
1103 }
1104 
1105 
LogStream.h
yarp::sig::file::read
bool read(ImageOf< PixelRgb > &dest, const std::string &src, image_fileformat format=FORMAT_ANY)
Definition: ImageFile.cpp:827
yarp::sig
Signal processing.
Definition: Image.h:25
yCWarning
#define yCWarning(component,...)
Definition: LogComponent.h:146
YARP_LOG_COMPONENT
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:80
yarp::sig::file::FORMAT_PGM
@ FORMAT_PGM
Definition: ImageFile.h:29
yError
#define yError(...)
Definition: Log.h:282
yarp::sig::file::FORMAT_JPG
@ FORMAT_JPG
Definition: ImageFile.h:31
VOCAB_PIXEL_RGBA
@ VOCAB_PIXEL_RGBA
Definition: Image.h:51
yarp::sig::ImageOf< PixelRgb >
yarp::sig::file::image_fileformat
image_fileformat
Definition: ImageFile.h:26
yarp::sig::file::FORMAT_NUMERIC
@ FORMAT_NUMERIC
Definition: ImageFile.h:32
yarp::sig::file::FORMAT_NUMERIC_COMPRESSED
@ FORMAT_NUMERIC_COMPRESSED
Definition: ImageFile.h:33
LogComponent.h
ImageFile.h
yarp::sig::file::FORMAT_PPM
@ FORMAT_PPM
Definition: ImageFile.h:30
yCError
#define yCError(component,...)
Definition: LogComponent.h:157
VOCAB_PIXEL_MONO
@ VOCAB_PIXEL_MONO
Definition: Image.h:48
yarp::os
An interface to the operating system, including Port based communication.
Definition: AbstractCarrier.h:17
yarp::sig::Image
Base class for storing images.
Definition: Image.h:85
VOCAB_PIXEL_RGB
@ VOCAB_PIXEL_RGB
Definition: Image.h:50
yarp::sig::file::FORMAT_PNG
@ FORMAT_PNG
Definition: ImageFile.h:34
yarp::sig::file::write
bool write(const ImageOf< PixelRgb > &src, const std::string &dest, image_fileformat format=FORMAT_PPM)
Definition: ImageFile.cpp:971
VOCAB_PIXEL_BGR
@ VOCAB_PIXEL_BGR
Definition: Image.h:55
yarp::sig::ImageOf::getPixelSize
size_t getPixelSize() const override
Definition: Image.h:657
VOCAB_PIXEL_MONO_FLOAT
@ VOCAB_PIXEL_MONO_FLOAT
Definition: Image.h:59
yarp::sig::Image::getPixelCode
virtual int getPixelCode() const
Gets pixel type identifier.
Definition: Image.cpp:454