YARP
Yet Another Robot Platform
ImageFile.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2018 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/Log.h>
12 #include <yarp/os/LogStream.h>
13 
14 #include <cstdio>
15 #include <cstdlib>
16 
17 #if YARP_HAS_JPEG_C
18 #include "jpeglib.h"
19 #endif
20 
21 using namespace std;
22 using namespace yarp::os;
23 using namespace yarp::sig;
24 
26 // private read methods
28 
29 static bool ReadHeader(FILE *fp, int *height, int *width, int *color)
30 {
31  char ch;
32  int maxval;
33 
34  *color = 0;
35 
37  if (fscanf(fp, "P%c\n", &ch) != 1 || (ch!='6'&&ch!='5'))
38  {
39  yWarning("file is not in pgm/ppm raw format; cannot read");
40  return false;
41  }
42 
43  if (ch=='6') *color = 1;
44 
45  // skip comments
46  ch = fgetc(fp);
47  while (ch == '#')
48  {
49  do
50  {
51  ch = fgetc(fp);
52  }
53  while (ch != '\n');
54  ch = fgetc(fp);
55  }
56  ungetc(ch, fp);
57 
59  int n=fscanf(fp, "%d%d%d", width, height, &maxval);
60  if (n!=3)
61  return false;
62 
63  fgetc(fp);
64  if (maxval != 255)
65  {
66  //die("image is not true-color (24 bit); read failed");
67  yWarning("image is not true-color (24 bit); read failed");
68  return false;
69  }
70 
71  return true;
72 }
73 
74 
75 static bool ImageReadRGB(ImageOf<PixelRgb> &img, const char *filename)
76 {
77  int width, height, color, num;
78  FILE *fp=nullptr;
79  fp = fopen(filename, "rb");
80 
81  if(fp==nullptr)
82  {
83  yError("Error opening %s, check if file exists.\n", filename);
84  return false;
85  }
86 
87  if (!ReadHeader(fp, &height, &width, &color))
88  {
89  fclose (fp);
90  yError("Error reading header, is file a valid ppm/pgm?\n");
91  return false;
92  }
93 
94  if (!color)
95  {
97  tmp.resize(width,height);
98 
99  const int w = tmp.width() * tmp.getPixelSize();
100  const int h = tmp.height();
101  const int pad = tmp.getRowSize();
102  unsigned char *dst = tmp.getRawImage ();
103 
104  num = 0;
105  for (int i = 0; i < h; i++)
106  {
107  num += (int)fread((void *) dst, 1, (size_t) w, fp);
108  dst += pad;
109  }
110  fclose(fp);
111  img.copy(tmp);
112  return true;
113  }
114 
115  img.resize(width,height);
116 
117  const int w = img.width() * img.getPixelSize();
118  const int h = img.height();
119  const int pad = img.getRowSize();
120  unsigned char *dst = img.getRawImage ();
121 
122  num = 0;
123  for (int i = 0; i < h; i++)
124  {
125  num += (int)fread((void *) dst, 1, (size_t) w, fp);
126  dst += pad;
127  }
128 
129  fclose(fp);
130 
131  return true;
132 }
133 
134 static bool ImageReadFloat(ImageOf<PixelFloat>& dest, const std::string& filename)
135 {
136  FILE *fp = fopen(filename.c_str(), "rb");
137  if (fp == nullptr) {
138  return false;
139  }
140 
141  size_t br = 0;
142  size_t size_ = sizeof(float);
143  size_t count_ = 0;
144 
145  size_t dims[2];
146  if (fread(dims, sizeof(dims), 1, fp) > 0)
147  {
148  count_ = (size_t)(dims[0] * dims[1]);
149  dest.resize(dims[0], dims[1]);
150  br = fread(&dest(0, 0), size_, count_, fp);
151  }
152 
153  fclose(fp);
154  return (br > 0);
155 }
156 
157 static bool ImageReadBGR(ImageOf<PixelBgr> &img, const char *filename)
158 {
159  int width, height, color, num;
160  FILE *fp=nullptr;
161  fp = fopen(filename, "rb");
162 
163  if(fp==nullptr)
164  {
165  yError("Error opening %s, check if file exists.\n", filename);
166  return false;
167  }
168 
169  if (!ReadHeader(fp, &height, &width, &color))
170  {
171  fclose (fp);
172  yError("Error reading header, is file a valid ppm/pgm?\n");
173  return false;
174  }
175 
176  if (!color)
177  {
178  fclose(fp);
179  yError("File is grayscale, conversion not yet supported\n");
180  return false;
181  }
182 
183  ImageOf<PixelRgb> tmpImg;
184  tmpImg.resize(width, height);
185 
186  const int w = tmpImg.width() * img.getPixelSize();
187  const int h = tmpImg.height();
188  const int pad = tmpImg.getRowSize();
189  unsigned char *dst = tmpImg.getRawImage ();
190 
191  num = 0;
192  for (int i = 0; i < h; i++)
193  {
194  num += (int)fread((void *) dst, 1, (size_t) w, fp);
195  dst += pad;
196  }
197 
198  fclose(fp);
199 
200  return img.copy(tmpImg);
201 }
202 
203 
204 static bool ImageReadMono(ImageOf<PixelMono> &img, const char *filename)
205 {
206  int width, height, color, num;
207  FILE *fp=nullptr;
208  fp = fopen(filename, "rb");
209 
210  if(fp==nullptr)
211  {
212  yError("Error opening %s, check if file exists.\n", filename);
213  return false;
214  }
215 
216  if (!ReadHeader(fp, &height, &width, &color))
217  {
218  fclose (fp);
219  yError("Error reading header, is file a valid ppm/pgm?\n");
220  return false;
221  }
222 
223  if (color)
224  {
225  fclose(fp);
226  yError("File is color, conversion not yet supported\n");
227  return false;
228  }
229 
230  img.resize(width,height);
231 
232  const int w = img.width() * img.getPixelSize();
233  const int h = img.height();
234  const int pad = img.getRowSize();
235  unsigned char *dst = img.getRawImage ();
236 
237  num = 0;
238  for (int i = 0; i < h; i++)
239  {
240  num += (int)fread((void *) dst, 1, (size_t) w, fp);
241  dst += pad;
242  }
243 
244  fclose(fp);
245 
246  return true;
247 }
248 
250 // private write methods
252 
253 static bool SaveJPG(char *src, const char *filename, int h, int w, int rowSize)
254 {
255 #if YARP_HAS_JPEG_C
256  int quality = 100;
257  struct jpeg_compress_struct cinfo;
258  struct jpeg_error_mgr jerr;
259  FILE * outfile;
260  JSAMPROW row_pointer[1];
261  int row_stride;
262 
263  cinfo.err = jpeg_std_error(&jerr);
264  jpeg_create_compress(&cinfo);
265 
266  if ((outfile = fopen(filename, "wb")) == NULL)
267  {
268  yError("can't write file: %s\n", filename);
269  return false;
270  }
271  jpeg_stdio_dest(&cinfo, outfile);
272 
273  cinfo.image_width = w;
274  cinfo.image_height = h;
275  cinfo.input_components = 3;
276  cinfo.in_color_space = JCS_RGB;
277  jpeg_set_defaults(&cinfo);
278  jpeg_set_quality(&cinfo, quality, TRUE);
279 
280  jpeg_start_compress(&cinfo, TRUE);
281 
282  row_stride = w * 3;
283 
284  while (cinfo.next_scanline < cinfo.image_height)
285  {
286  row_pointer[0] = (JSAMPROW)&src[cinfo.next_scanline * row_stride];
287  (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
288  }
289 
290  jpeg_finish_compress(&cinfo);
291  fclose(outfile);
292  jpeg_destroy_compress(&cinfo);
293  return true;
294 #else
295  yError() << "libjpeg not installed";
296  return false;
297 #endif
298 }
299 
300 static bool SavePGM(char *src, const char *filename, int h, int w, int rowSize)
301 {
302  FILE *fp = fopen(filename, "wb");
303  if (!fp)
304  {
305  yError("cannot open file %s for writing\n", filename);
306  return false;
307  }
308  else
309  {
310  const int inc = rowSize;
311 
312  fprintf(fp, "P5\n%d %d\n%d\n", w, h, 255);
313  for (int i = 0; i < h; i++)
314  {
315  fwrite((void *)src, 1, (size_t)w, fp);
316  src += inc;
317  }
318 
319  fclose(fp);
320  }
321 
322  return true;
323 }
324 
325 
326 static bool SavePPM(char *src, const char *filename, int h, int w, int rowSize)
327 {
328  FILE *fp = fopen(filename, "wb");
329  if (!fp)
330  {
331  yError("cannot open file %s for writing\n", filename);
332  return false;
333  }
334  else
335  {
336  const int inc = rowSize;//YARPSimpleOperation::ComputePadding (w*3, YarpImageAlign) + w * 3;
337 
338  fprintf(fp, "P6\n%d %d\n%d\n", w, h, 255);
339  for (int i = 0; i < h; i++)
340  {
341  fwrite((void *)src, 1, (size_t)(w * 3), fp);
342  src += inc;
343  }
344 
346  fclose(fp);
347  }
348 
349  return true;
350 }
351 
352 static bool ImageWriteJPG(ImageOf<PixelRgb>& img, const char *filename)
353 {
354  return SaveJPG((char*)img.getRawImage(), filename, img.height(), img.width(), img.getRowSize());
355 }
356 
357 static bool ImageWriteRGB(ImageOf<PixelRgb>& img, const char *filename)
358 {
359  return SavePPM((char*)img.getRawImage(),filename,img.height(),img.width(),img.getRowSize());
360 }
361 
362 static bool ImageWriteMono(ImageOf<PixelMono>& img, const char *filename)
363 {
364  return SavePGM((char*)img.getRawImage(), filename, img.height(), img.width(), img.getRowSize());
365 }
366 
367 static bool ImageWriteFloat(ImageOf<PixelFloat>& img, const char *filename)
368 {
369  FILE *fp = fopen(filename, "wb");
370  if (fp == nullptr)
371  {
372  return false;
373  }
374 
375  size_t dims[2] = { img.width(), img.height() };
376 
377  size_t bw = 0;
378  size_t size_ = sizeof(float);
379  size_t count_ = (size_t)(dims[0] * dims[1]);
380 
381  if (fwrite(dims, sizeof(dims), 1, fp) > 0) {
382  bw = fwrite(&img(0, 0), size_, count_, fp);
383  }
384 
385  fclose(fp);
386  return (bw > 0);
387 }
388 
390 // public read methods
392 
393 bool file::read(ImageOf<PixelRgb> & dest, const std::string& src, image_fileformat format)
394 {
395  return ImageReadRGB(dest,src.c_str());
396 }
397 
398 
399 bool file::read(ImageOf<PixelBgr> & dest, const std::string& src, image_fileformat format)
400 {
401  return ImageReadBGR(dest,src.c_str());
402 }
403 
404 
405 bool file::read(ImageOf<PixelRgba> & dest, const std::string& src, image_fileformat format)
406 {
407  ImageOf<PixelRgb> img2;
408  bool ok = ImageReadRGB(img2,src.c_str());
409  if (ok)
410  {
411  dest.copy(img2);
412  }
413  return ok;
414 }
415 
416 bool file::read(ImageOf<PixelMono> & dest, const std::string& src, image_fileformat format)
417 {
418  return ImageReadMono(dest, src.c_str());
419 }
420 
421 bool file::read(ImageOf<PixelFloat>& dest, const std::string& src, image_fileformat format)
422 {
423  return ImageReadFloat(dest, src.c_str());
424 }
425 
429 
430 bool file::write(const ImageOf<PixelRgb> & src, const std::string& dest, image_fileformat format)
431 {
432  if (format == FORMAT_PPM)
433  {
434  return ImageWriteRGB(const_cast<ImageOf<PixelRgb> &>(src), dest.c_str());
435  }
436  else if (format == FORMAT_JPG)
437  {
438  return ImageWriteJPG(const_cast<ImageOf<PixelRgb> &>(src), dest.c_str());
439  }
440  else
441  {
442  yError() << "Invalid format, operation not supported";
443  return false;
444  }
445 }
446 
447 bool file::write(const ImageOf<PixelBgr> & src, const std::string& dest, image_fileformat format)
448 {
449  ImageOf<PixelRgb> imgRGB;
450  imgRGB.copy(src);
451  if (format == FORMAT_PPM)
452  {
453  return ImageWriteRGB(const_cast<ImageOf<PixelRgb> &>(imgRGB), dest.c_str());
454  }
455  else if (format == FORMAT_JPG)
456  {
457  return ImageWriteJPG(const_cast<ImageOf<PixelRgb> &>(imgRGB), dest.c_str());
458  }
459  else
460  {
461  yError() << "Invalid format, operation not supported";
462  return false;
463  }
464 }
465 
466 
467 bool file::write(const ImageOf<PixelRgba> & src, const std::string& dest, image_fileformat format)
468 {
469  ImageOf<PixelRgb> imgRGB;
470  imgRGB.copy(src);
471  if (format == FORMAT_PPM)
472  {
473  return ImageWriteRGB(const_cast<ImageOf<PixelRgb> &>(imgRGB), dest.c_str());
474  }
475  else if (format == FORMAT_JPG)
476  {
477  return ImageWriteJPG(const_cast<ImageOf<PixelRgb> &>(imgRGB), dest.c_str());
478  }
479  else
480  {
481  yError() << "Invalid format, operation not supported";
482  return false;
483  }
484 }
485 
486 
487 bool file::write(const ImageOf<PixelMono> & src, const std::string& dest, image_fileformat format)
488 {
489  if (format == FORMAT_PGM)
490  {
491  return ImageWriteMono(const_cast<ImageOf<PixelMono> &>(src), dest.c_str());
492  }
493  else
494  {
495  yError() << "Invalid format, operation not supported";
496  return false;
497  }
498 }
499 
500 bool file::write(const ImageOf<PixelFloat>& src, const std::string& dest, image_fileformat format)
501 {
502  if (format == FORMAT_NUMERIC)
503  {
504  return ImageWriteFloat(const_cast<ImageOf<PixelFloat> &>(src), dest.c_str());
505  }
506  else
507  {
508  yError() << "Invalid format, operation not supported";
509  return false;
510  }
511 }
512 
513 bool file::write(const Image& src, const std::string& dest, image_fileformat format)
514 {
515  int code=src.getPixelCode();
516  if (code == VOCAB_PIXEL_MONO)
517  {
518  return write(static_cast<const ImageOf<PixelMono>&>(src), dest, format);
519  }
520  else if (code == VOCAB_PIXEL_MONO_FLOAT)
521  {
522  return write(static_cast<const ImageOf<PixelFloat>&>(src), dest, format);
523  }
524  else if (code == VOCAB_PIXEL_BGR)
525  {
526  return write(static_cast<const ImageOf<PixelBgr>&>(src), dest, format);
527  }
528  else if (code == VOCAB_PIXEL_RGB)
529  {
530  return write(static_cast<const ImageOf<PixelRgb>&>(src), dest, format);
531  }
532  else if (code == VOCAB_PIXEL_RGBA)
533  {
534  return write(static_cast<const ImageOf<PixelRgba>&>(src), dest, format);
535  }
536  else
537  {
538  ImageOf<PixelRgb> img;
539  img.copy(src);
540  return write(img,dest);
541  }
542 }
543 
544 
bool write(const ImageOf< PixelRgb > &src, const std::string &dest, image_fileformat format=FORMAT_PPM)
Definition: ImageFile.cpp:430
unsigned char * getRawImage() const
Access to the internal image buffer.
Definition: Image.cpp:526
static bool ImageWriteFloat(ImageOf< PixelFloat > &img, const char *filename)
Definition: ImageFile.cpp:367
bool read(ImageOf< PixelRgb > &dest, const std::string &src, image_fileformat format=FORMAT_ANY)
Definition: ImageFile.cpp:393
bool copy(const Image &alt)
Copy operator.
Definition: Image.cpp:807
static bool ImageReadRGB(ImageOf< PixelRgb > &img, const char *filename)
Definition: ImageFile.cpp:75
static bool ImageReadFloat(ImageOf< PixelFloat > &dest, const std::string &filename)
Definition: ImageFile.cpp:134
virtual size_t getPixelSize() const override
Gets pixel size in memory in bytes.
Definition: Image.h:575
size_t getRowSize() const
Size of the underlying image buffer rows.
Definition: Image.h:164
STL namespace.
static bool SavePGM(char *src, const char *filename, int h, int w, int rowSize)
Definition: ImageFile.cpp:300
static bool ReadHeader(FILE *fp, int *height, int *width, int *color)
Definition: ImageFile.cpp:29
size_t width() const
Gets width of image in pixels.
Definition: Image.h:138
Base class for storing images.
Definition: Image.h:85
void resize(size_t imgWidth, size_t imgHeight)
Reallocate an image to be of a desired size, throwing away its current contents.
Definition: Image.cpp:462
static bool ImageReadBGR(ImageOf< PixelBgr > &img, const char *filename)
Definition: ImageFile.cpp:157
static bool SavePPM(char *src, const char *filename, int h, int w, int rowSize)
Definition: ImageFile.cpp:326
static bool SaveJPG(char *src, const char *filename, int h, int w, int rowSize)
Definition: ImageFile.cpp:253
#define yWarning
Definition: Log.h:100
#define yError
Definition: Log.h:101
size_t height() const
Gets height of image in pixels.
Definition: Image.h:144
static bool ImageWriteRGB(ImageOf< PixelRgb > &img, const char *filename)
Definition: ImageFile.cpp:357
static bool ImageWriteMono(ImageOf< PixelMono > &img, const char *filename)
Definition: ImageFile.cpp:362
An interface to the operating system, including Port based communication.
static bool ImageReadMono(ImageOf< PixelMono > &img, const char *filename)
Definition: ImageFile.cpp:204
Signal processing.
Definition: Image.h:25
static bool ImageWriteJPG(ImageOf< PixelRgb > &img, const char *filename)
Definition: ImageFile.cpp:352
virtual int getPixelCode() const
Gets pixel type identifier.
Definition: Image.cpp:450