YARP
Yet Another Robot Platform
Image.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 /*
11  This file is in a pretty hacky state. Sorry!
12 
13 */
14 
15 #include <yarp/sig/Image.h>
16 
17 #include <yarp/os/Bottle.h>
20 #include <yarp/os/Log.h>
21 #include <yarp/os/Time.h>
22 #include <yarp/os/Vocab.h>
23 
25 #include <yarp/sig/impl/IplImage.h>
26 #include <yarp/sig/impl/DeBayer.h>
27 
28 #include <cstdio>
29 #include <cstring>
30 #include <string>
31 
32 
33 using namespace yarp::sig;
34 using namespace yarp::os;
35 
36 #define DBGPF1 if (0)
37 
38 //inline int PAD_BYTES (int len, int pad)
39 //{
40 // const int rem = len % pad;
41 // return (rem != 0) ? (pad - rem) : rem;
42 //}
43 
48 inline bool readFromConnection(Image &dest, ImageNetworkHeader &header, ConnectionReader& connection)
49 {
50  dest.resize(header.width, header.height);
51  unsigned char *mem = dest.getRawImage();
52  size_t allocatedBytes = dest.getRawImageSize();
53  yAssert(mem != nullptr);
54  //this check is redundant with assertion, I would remove it
55  if (dest.getRawImageSize() != static_cast<size_t>(header.imgSize)) {
56  printf("There is a problem reading an image\n");
57  printf("incoming: width %zu, height %zu, code %zu, quantum %zu, size %zu\n",
58  static_cast<size_t>(header.width),
59  static_cast<size_t>(header.height),
60  static_cast<size_t>(header.id),
61  static_cast<size_t>(header.quantum),
62  static_cast<size_t>(header.imgSize));
63  printf("my space: width %zu, height %zu, code %d, quantum %zu, size %zu\n",
64  dest.width(), dest.height(), dest.getPixelCode(), dest.getQuantum(), allocatedBytes);
65  }
66  yAssert(allocatedBytes == (size_t) header.imgSize);
67  bool ok = connection.expectBlock(reinterpret_cast<char*>(mem), allocatedBytes);
68  return (!connection.isError() && ok);
69 }
70 
71 
72 
73 class ImageStorage {
74 public:
76  char **Data; // this is not IPL. it's char to maintain IPL compatibility
79  size_t quantum;
80  bool topIsLow;
81 
82 protected:
84 
85  int type_id;
86 
87  int is_owner;
88 
89  // ipl allocation is done in two steps.
90  // _alloc allocates the actual ipl pointer.
91  // _alloc_data allocates the image array and data.
92  // memory is allocated in a single chunk. Row ptrs are then
93  // made to point appropriately. This is compatible with IPL and
94  // SOMEONE says it's more efficient on NT.
95  void _alloc ();
96  void _alloc_extern (const void *buf);
97  void _alloc_data ();
98  void _free ();
99  void _free_data ();
100 
101  void _make_independent();
102  bool _set_ipl_header(size_t x, size_t y, int pixel_type, size_t quantum,
103  bool topIsLow);
104  void _free_ipl_header();
105  void _alloc_complete(size_t x, size_t y, int pixel_type, size_t quantum,
106  bool topIsLow);
107  void _free_complete();
108 
109 
110  // computes the # of padding bytes. These are always at the end of the row.
111  int _pad_bytes (size_t linesize, size_t align) const;
112 
113  inline int GetPadding() const {
114  return _pad_bytes (pImage->width * pImage->nChannels,
116  }
117 
118 public:
119  ImageStorage(Image& owner) : owner(owner) {
120  type_id = 0;
121  pImage = nullptr;
122  Data = nullptr;
123  is_owner = 1;
124  quantum = 0;
125  topIsLow = true;
126  extern_type_id = 0;
127  extern_type_quantum = -1;
128  }
129 
131  _free_complete();
132  }
133 
134  void resize(size_t x, size_t y, int pixel_type,
135  size_t quantum, bool topIsLow);
136 
137  void _alloc_complete_extern(const void *buf, size_t x, size_t y, int pixel_type,
138  size_t quantum, bool topIsLow);
139  int getTypeId();
140 
141 };
142 
143 
144 void ImageStorage::resize(size_t x, size_t y, int pixel_type,
145  size_t quantum, bool topIsLow) {
146  int need_recreation = 1;
147 
148  if (quantum==0) {
149  quantum = YARP_IMAGE_ALIGN;
150  }
151 
152  if (need_recreation) {
153  _free_complete();
154  DBGPF1 printf("HIT recreation for %p %p: %zu %zu %d\n", static_cast<void*>(this), static_cast<void*>(pImage), x, y, pixel_type);
155  _alloc_complete (x, y, pixel_type, quantum, topIsLow);
156  }
157  extern_type_id = pixel_type;
158  extern_type_quantum = quantum;
159 }
160 
166  return type_id;
167 }
168 
169 
170 // allocates an empty image.
172 
173 
174  _free(); // was iplDeallocateImage(pImage); but that won't work with refs
175 
176  if ((type_id == VOCAB_PIXEL_MONO_FLOAT) ||
177  (type_id == VOCAB_PIXEL_RGB_FLOAT) ||
178  (type_id == VOCAB_PIXEL_HSV_FLOAT)) {
179  iplAllocateImageFP(pImage, 0, 0);
180  } else {
181  iplAllocateImage (pImage, 0, 0);
182  }
183 
185 }
186 
187 // installs an external buffer as the image data
188 void ImageStorage::_alloc_extern (const void *buf)
189 {
190  yAssert(pImage != nullptr);
191  yAssert(Data==nullptr);
192 
193  if (pImage != nullptr) {
194  if (pImage->imageData != nullptr) {
195  iplDeallocateImage (pImage);
196  }
197  }
198 
199  //iplAllocateImage (pImage, 0, 0);
200  pImage->imageData = const_cast<char*>(reinterpret_cast<const char*>(buf));
201  // probably need to do more for real IPL
202 
203  //iplSetBorderMode (pImage, IPL_BORDER_CONSTANT, IPL_SIDE_ALL, 0);
204 }
205 
206 // allocates the Data pointer.
208 {
209  DBGPF1 printf("alloc_data1\n"), fflush(stdout);
210  yAssert(pImage != nullptr);
211 
212  yAssert(Data==nullptr);
213 
214  char **ptr = new char *[pImage->height];
215 
216  Data = ptr;
217 
218  yAssert(Data != nullptr);
219 
220  yAssert(pImage->imageData != nullptr);
221 
222  int height = pImage->height;
223 
224  char * DataArea = pImage->imageData;
225 
226  for (int r = 0; r < height; r++)
227  {
228  if (topIsLow) {
229  Data[r] = DataArea;
230  } else {
231  Data[height-r-1] = DataArea;
232  }
233  DataArea += pImage->widthStep;
234  }
235  DBGPF1 printf("alloc_data4\n");
236 }
237 
239 {
240  if (pImage != nullptr) {
241  if (pImage->imageData != nullptr) {
242  if (is_owner) {
243  iplDeallocateImage (pImage);
244  delete[] Data;
245  } else {
246  delete[] Data;
247  }
248 
249  is_owner = 1;
250  Data = nullptr;
251  pImage->imageData = nullptr;
252  }
253  }
254 }
255 
257 {
258  yAssert(Data==nullptr); // Now always free Data at same time
259 }
260 
261 
263 {
264  _free();
265  _free_data();
266  _free_ipl_header();
267 }
268 
269 
271 {
272  if (pImage!=nullptr)
273  {
275  }
276  pImage = nullptr;
277 }
278 
279 
280 void ImageStorage::_alloc_complete(size_t x, size_t y, int pixel_type, size_t quantum,
281  bool topIsLow)
282 {
283  _make_independent();
284  _free_complete();
285  _set_ipl_header(x, y, pixel_type, quantum, topIsLow);
286  _alloc ();
287  _alloc_data ();
288 }
289 
290 
291 
293 {
294  // actually I think this isn't really needed -paulfitz
295 }
296 
298 {
300  int depth;
301  const char* colorModel;
302  const char* channelSeq;
303 };
304 
307 
308 const std::map<int, pixelTypeIplParams> pixelCode2iplParams = {
323  {VOCAB_PIXEL_RGB, {3, IPL_DEPTH_8U, "RGB", "RGB" }},
324  {VOCAB_PIXEL_RGBA, {4, IPL_DEPTH_8U, "RGBA", "RGBA"}},
325  {VOCAB_PIXEL_BGRA, {4, IPL_DEPTH_8U, "BGRA", "BGRA"}},
326  {VOCAB_PIXEL_INT, {1, IPL_DEPTH_32S, "GRAY", "GRAY"}},
327  {VOCAB_PIXEL_HSV, {3, IPL_DEPTH_8U, "HSV", "HSV" }},
328  {VOCAB_PIXEL_BGR, {3, IPL_DEPTH_8U, "RGB", "BGR" }},
329  {VOCAB_PIXEL_MONO_SIGNED, {1, IPL_DEPTH_8S, "GRAY", "GRAY"}},
330  {VOCAB_PIXEL_RGB_INT, {3, IPL_DEPTH_32S, "RGB", "RGB" }},
331  {VOCAB_PIXEL_MONO_FLOAT, {1, IPL_DEPTH_32F, "GRAY", "GRAY"}},
332  {VOCAB_PIXEL_RGB_FLOAT, {3, IPL_DEPTH_32F, "RGB", "RGB" }},
333  {-2, iplPixelTypeMono16},
334  {-4, {1, IPL_DEPTH_32S, "GRAY", "GRAY"}}
335 };
336 
337 bool ImageStorage::_set_ipl_header(size_t x, size_t y, int pixel_type, size_t quantum,
338  bool topIsLow)
339 {
340  if (pImage != nullptr) {
341  iplDeallocateImage(pImage);
342  pImage = nullptr;
343  }
344 
345  if (pixel_type == VOCAB_PIXEL_INVALID) {
346  // not a type!
347  printf ("*** Trying to allocate an invalid pixel type image\n");
348  std::exit(1);
349  }
350  if (pixelCode2iplParams.find(pixel_type) == pixelCode2iplParams.end()) {
351  // unknown pixel type. Should revert to a non-IPL mode... how?
352  return false;
353  }
354 
355  const pixelTypeIplParams& param = pixelCode2iplParams.at(pixel_type);
356 
357  if (quantum==0) {
358  quantum = IPL_ALIGN_QWORD;
359  }
360  int origin = topIsLow ? IPL_ORIGIN_TL : IPL_ORIGIN_BL;
361 
362  pImage = iplCreateImageHeader(param.nChannels, 0, param.depth, const_cast<char*>(param.colorModel), const_cast<char*>(param.channelSeq), IPL_DATA_ORDER_PIXEL, origin, quantum, x, y, nullptr, nullptr, nullptr, nullptr);
363 
364  type_id = pixel_type;
365  this->quantum = quantum;
366  this->topIsLow = topIsLow;
367  return true;
368 }
369 
370 void ImageStorage::_alloc_complete_extern(const void *buf, size_t x, size_t y, int pixel_type, size_t quantum, bool topIsLow)
371 {
372  if (quantum==0) {
373  quantum = 1;
374  }
375  this->quantum = quantum;
376  this->topIsLow = topIsLow;
377 
378  _make_independent();
379  _free_complete();
380  _set_ipl_header(x, y, pixel_type, quantum, topIsLow);
381  Data = nullptr;
382  _alloc_extern (buf);
383  _alloc_data ();
384  is_owner = 0;
385 }
386 
387 
388 
389 int ImageStorage::_pad_bytes (size_t linesize, size_t align) const
390 {
391  return yarp::sig::PAD_BYTES (linesize, align);
392 }
393 
394 const std::map<YarpVocabPixelTypesEnum, size_t> Image::pixelCode2Size = {
395  {VOCAB_PIXEL_INVALID, 0 },
418  {VOCAB_PIXEL_YUV_420, 1},
419  {VOCAB_PIXEL_YUV_444, 1},
420  {VOCAB_PIXEL_YUV_422, 1},
422 };
423 
425  initialize();
426 }
427 
428 void Image::initialize() {
429  implementation = nullptr;
430  data = nullptr;
431  imgWidth = imgHeight = 0;
432  imgPixelSize = imgRowSize = 0;
433  imgPixelCode = 0;
434  imgQuantum = 0;
435  topIsLow = true;
436  implementation = new ImageStorage(*this);
437  yAssert(implementation!=nullptr);
438 }
439 
440 
442  if (implementation!=nullptr) {
443  delete static_cast<ImageStorage*>(implementation);
444  implementation = nullptr;
445  }
446 }
447 
448 
449 size_t Image::getPixelSize() const {
450  return imgPixelSize;
451 }
452 
453 
454 int Image::getPixelCode() const {
455  return imgPixelCode;
456 }
457 
458 
459 void Image::zero() {
460  if (getRawImage()!=nullptr) {
461  memset(getRawImage(),0,getRawImageSize());
462  }
463 }
464 
465 
466 void Image::resize(size_t imgWidth, size_t imgHeight) {
467 
468  int code = getPixelCode();
469  bool change = false;
470  if (code!=imgPixelCode) {
471  setPixelCode(code);
472  change = true;
473  }
474  if (imgPixelCode!=(static_cast<ImageStorage*>(implementation))->extern_type_id) {
475  change = true;
476  }
477  if (imgQuantum!=(static_cast<ImageStorage*>(implementation))->extern_type_quantum) {
478  change = true;
479  }
480 
481  if (imgWidth!=width()||imgHeight!=height()) {
482  change = true;
483  }
484 
485  if (change) {
486  (static_cast<ImageStorage*>(implementation))->resize(imgWidth,
487  imgHeight,
488  imgPixelCode,
489  imgQuantum,
490  topIsLow);
491  synchronize();
492  //printf("CHANGE! %ld\n", (long int)(this));
493  }
494 }
495 
496 void Image::setPixelSize(size_t imgPixelSize) {
497  if(imgPixelSize == pixelCode2Size.at(static_cast<YarpVocabPixelTypesEnum>(imgPixelCode))) {
498  return;
499  }
500 
501  setPixelCode(-imgPixelSize);
502 }
503 
504 void Image::setPixelCode(int imgPixelCode) {
505  this->imgPixelCode = imgPixelCode;
506  this->imgPixelSize = (imgPixelCode < 0) ? -imgPixelCode : pixelCode2Size.at(static_cast<YarpVocabPixelTypesEnum>(imgPixelCode));
507 }
508 
509 
510 void Image::setQuantum(size_t imgQuantum) {
511  this->imgQuantum = imgQuantum;
512 }
513 
514 
515 void Image::synchronize() {
516  auto* impl = static_cast<ImageStorage*>(implementation);
517  yAssert(impl!=nullptr);
518  if (impl->pImage!=nullptr) {
519  imgWidth = impl->pImage->width;
520  imgHeight = impl->pImage->height;
521  data = impl->Data;
522  imgQuantum = impl->quantum;
523  imgRowSize = impl->pImage->widthStep;
524  setPixelCode(impl->getTypeId());
525  topIsLow = impl->pImage->origin == IPL_ORIGIN_TL;
526  } else {
527  data = nullptr;
528  imgWidth = 0;
529  imgHeight = 0;
530  }
531 }
532 
533 
534 unsigned char *Image::getRawImage() const {
535  auto* impl = static_cast<ImageStorage*>(implementation);
536  yAssert(impl!=nullptr);
537  if (impl->pImage!=nullptr) {
538  return reinterpret_cast<unsigned char*>(impl->pImage->imageData);
539  }
540  return nullptr;
541 }
542 
543 size_t Image::getRawImageSize() const {
544  auto* impl = static_cast<ImageStorage*>(implementation);
545  yAssert(impl!=nullptr);
546  if (impl->pImage!=nullptr) {
547  return impl->pImage->imageSize;
548  }
549  return 0;
550 }
551 
552 #ifndef YARP_NO_DEPRECATED // Since YARP 3.2.0
554  return (static_cast<ImageStorage*>(implementation))->pImage;
555 }
556 
557 const void *Image::getIplImage() const {
558  return (static_cast<const ImageStorage*>(implementation))->pImage;
559 }
560 
561 void Image::wrapIplImage(void *iplImage) {
562  yAssert(iplImage!=nullptr);
563  auto* p = static_cast<IplImage *>(iplImage);
564  std::string str = p->colorModel;
565  int code = -1;
566  int color_code = -1;
567  if (str=="rgb"||str=="RGB"||
568  str=="bgr"||str=="BGR"||
569  str=="gray"||str=="GRAY"||
570  str=="graygray"||str=="GRAYGRAY") {
571  str = p->channelSeq;
572  if (str=="rgb"||str=="RGB") {
573  color_code = VOCAB_PIXEL_RGB;
574  } else if (str=="bgr"||str=="BGR") {
575  color_code = VOCAB_PIXEL_BGR;
576  } else if (str=="gray"||str=="GRAY"||
577  str=="graygray"||str=="GRAYGRAY") {
578  color_code = VOCAB_PIXEL_MONO;
579  } else {
580  printf("specific IPL RGB order (%s) is not yet supported\n",
581  str.c_str());
582  printf("Try RGB, BGR, or \n");
583  printf("Or fix code at %s line %d\n",__FILE__,__LINE__);
584  std::exit(1);
585  }
586  }
587 
588  // Type translation is approximate. Patches welcome to flesh out
589  // the types available.
590  if (p->depth == IPL_DEPTH_8U) {
591  code = color_code;
592  } else if (p->depth == IPL_DEPTH_8S) {
593  switch (color_code) {
594  case VOCAB_PIXEL_MONO:
596  break;
597  case VOCAB_PIXEL_RGB:
598  code = VOCAB_PIXEL_RGB_SIGNED;
599  break;
600  case VOCAB_PIXEL_BGR:
601  code = color_code; // nothing better available
602  break;
603  }
604  } else if (p->depth == IPL_DEPTH_16U || p->depth == IPL_DEPTH_16S) {
605  switch (color_code) {
606  case VOCAB_PIXEL_MONO:
607  code = VOCAB_PIXEL_MONO16;
608  break;
609  case VOCAB_PIXEL_RGB:
610  case VOCAB_PIXEL_BGR:
611  fprintf(stderr,"No translation currently available for this pixel type\n");
612  std::exit(1);
613  break;
614  }
615  } else if (p->depth == IPL_DEPTH_32S) {
616  switch (color_code) {
617  case VOCAB_PIXEL_MONO:
618  code = VOCAB_PIXEL_INT;
619  break;
620  case VOCAB_PIXEL_RGB:
621  case VOCAB_PIXEL_BGR:
622  code = VOCAB_PIXEL_RGB_INT;
623  break;
624  }
625  } else if (p->depth == IPL_DEPTH_32F) {
626  switch (color_code) {
627  case VOCAB_PIXEL_MONO:
628  code = VOCAB_PIXEL_MONO_FLOAT;
629  break;
630  case VOCAB_PIXEL_RGB:
631  case VOCAB_PIXEL_BGR:
632  code = VOCAB_PIXEL_RGB_FLOAT;
633  break;
634  }
635  }
636 
637  if (code==-1) {
638  fprintf(stderr,"IPL pixel type / depth combination is not yet supported\n");
639  fprintf(stderr,"Please email a YARP developer to complain, quoting this:\n");
640  fprintf(stderr," %s:%d\n", __FILE__, __LINE__);
641  }
642 
643  if (getPixelCode()!=code && getPixelCode()!=-1) {
644  printf("your specific IPL format (%s depth %d -> %s) does not match your YARP format (%s)\n",
645  str.c_str(),
646  p->depth,
647  Vocab::decode(code).c_str(),
648  Vocab::decode(getPixelCode()).c_str());
649  printf("Making a copy instead of just wrapping...\n");
650  FlexImage img;
651  img.setQuantum(p->align);
652  img.setPixelCode(code);
653  img.setExternal(p->imageData,p->width,p->height);
654  copy(img);
655  } else {
656  setQuantum(p->align);
657  setPixelCode(code);
658  setExternal(p->imageData,p->width,p->height);
659  }
660 }
661 
662 #endif // YARP_NO_DEPRECATED
663 
664 
666 
667  // auto-convert text mode interaction
668  connection.convertTextMode();
669 
670  ImageNetworkHeader header;
671 
672  bool ok = connection.expectBlock(reinterpret_cast<char*>(&header),sizeof(header));
673  if (!ok) {
674  return false;
675  }
676 
677  //first check that the received image size is reasonable
678  if (header.width == 0 || header.height == 0)
679  {
680  // I maintain the previous logic, although we should probably return false
681  return !connection.isError();
682  }
683 
684  setPixelCode(header.id);
685 
686  size_t q = getQuantum();
687  if (q==0) {
688  //q = YARP_IMAGE_ALIGN;
689  setQuantum(header.quantum);
690  q = getQuantum();
691  }
692  if (q != static_cast<size_t>(header.quantum)) {
693  if ((header.depth*header.width)%header.quantum==0 &&
694  (header.depth*header.width)%q==0) {
695  header.quantum = q;
696  }
697  }
698 
699  // handle easy case, received and current image are compatible, no conversion needed
700  if (getPixelCode() == header.id && q == static_cast<size_t>(header.quantum) && imgPixelSize == static_cast<size_t>(header.depth))
701  {
702  return readFromConnection(*this, header, connection);
703  }
704 
705  // image is bayer 8 bits, current image is MONO, copy as is (keep raw format)
706  if (getPixelCode() == VOCAB_PIXEL_MONO && isBayer8(header.id))
707  {
708  return readFromConnection(*this, header, connection);
709  }
710  // image is bayer 16 bits, current image is MONO16, copy as is (keep raw format)
711  if (getPixelCode() == VOCAB_PIXEL_MONO16 && isBayer16(header.id))
712  {
713  return readFromConnection(*this, header, connection);
714  }
715 
717  // Received and current images are binary incompatible do our best to convert
718  //
719 
720  // handle here all bayer encoding 8 bits
721  if (isBayer8(header.id))
722  {
723  FlexImage flex;
725  flex.setQuantum(header.quantum);
726 
727  bool ok = readFromConnection(flex, header, connection);
728  if (!ok) {
729  return false;
730  }
731 
732  if (getPixelCode() == VOCAB_PIXEL_BGR && header.id==VOCAB_PIXEL_ENCODING_BAYER_GRBG8) {
733  return deBayer_GRBG8_TO_BGR(flex, *this, 3);
734  }
735  if (getPixelCode() == VOCAB_PIXEL_BGRA && header.id == VOCAB_PIXEL_ENCODING_BAYER_GRBG8) {
736  return deBayer_GRBG8_TO_BGR(flex, *this, 4);
737  }
738  if (getPixelCode() == VOCAB_PIXEL_RGB && header.id==VOCAB_PIXEL_ENCODING_BAYER_GRBG8) {
739  return deBayer_GRBG8_TO_RGB(flex, *this, 3);
740  }
741  if (getPixelCode() == VOCAB_PIXEL_RGBA && header.id == VOCAB_PIXEL_ENCODING_BAYER_GRBG8) {
742  return deBayer_GRBG8_TO_RGB(flex, *this, 4);
743  }
744 
745  YARP_FIXME_NOTIMPLEMENTED("Conversion from bayer encoding not yet implemented\n");
746  return false;
747  }
748 
749  // handle here all bayer encodings 16 bits
750  if (isBayer16(header.id))
751  {
752  // as bayer16 seems unlikely we defer implementation for later
753  YARP_FIXME_NOTIMPLEMENTED("Conversion from bayer encoding 16 bits not yet implemented\n");
754  return false;
755  }
756 
757  // Received image has valid YARP pixels and can be converted using Image primitives
758  // prepare a FlexImage, set it to be compatible with the received image
759  // read new image into FlexImage then copy from it.
760  FlexImage flex;
761  flex.setPixelCode(header.id);
762  flex.setQuantum(header.quantum);
763  ok = readFromConnection(flex, header, connection);
764  if (ok) {
765  copy(flex);
766  }
767 
768  return ok;
769 }
770 
771 
772 bool Image::write(yarp::os::ConnectionWriter& connection) const {
773  ImageNetworkHeader header;
774  header.setFromImage(*this);
775  /*
776  header.listTag = BOTTLE_TAG_LIST;
777  header.listLen = 4;
778  header.paramNameTag = BOTTLE_TAG_VOCAB;
779  header.paramName = yarp::os::createVocab('m','a','t');
780  header.paramIdTag = BOTTLE_TAG_VOCAB;
781  header.id = getPixelCode();
782  header.paramListTag = BOTTLE_TAG_LIST + BOTTLE_TAG_INT32;
783  header.paramListLen = 5;
784  header.depth = getPixelSize();
785  header.imgSize = getRawImageSize();
786  header.quantum = getQuantum();
787  header.width = width();
788  header.height = height();
789  header.paramBlobTag = BOTTLE_TAG_BLOB;
790  header.paramBlobLen = getRawImageSize();
791  */
792 
793  connection.appendBlock(reinterpret_cast<char*>(&header),sizeof(header));
794  unsigned char *mem = getRawImage();
795  if (header.width!=0&&header.height!=0) {
796  yAssert(mem!=nullptr);
797 
798  // Note use of external block.
799  // Implies care needed about ownership.
800  connection.appendExternalBlock(reinterpret_cast<char *>(mem),header.imgSize);
801  }
802 
803  // if someone is foolish enough to connect in text mode,
804  // let them see something readable.
805  connection.convertTextMode();
806 
807  return !connection.isError();
808 }
809 
810 
811 Image::Image(const Image& alt) : Portable()
812 {
813  initialize();
814  copy(alt);
815 }
816 
817 Image::Image(Image&& other) noexcept
818  : implementation(other.implementation)
819 {
820  other.implementation = nullptr;
821  synchronize();
822 }
823 
824 Image& Image::operator=(Image&& other) noexcept
825 {
826  Image moved(std::move(other));
827  std::swap(moved.implementation, implementation);
828  synchronize();
829  return *this;
830 }
831 
832 
834 {
835  if (&alt != this) {
836  copy(alt);
837  }
838  return *this;
839 }
840 
841 
842 bool Image::copy(const Image& alt)
843 {
844  if (&alt != this)
845  {
846  int myCode = getPixelCode();
847  if (myCode==0) {
848  setPixelCode(alt.getPixelCode());
849  setQuantum(alt.getQuantum());
850  }
851  resize(alt.width(),alt.height());
852  int q1 = alt.getQuantum();
853  int q2 = getQuantum();
854  if (q1==0) { q1 = YARP_IMAGE_ALIGN; }
855  if (q2==0) { q2 = YARP_IMAGE_ALIGN; }
856 
857  bool o1 = alt.topIsLowIndex();
858  bool o2 = topIsLowIndex();
859 
860  yAssert(width()==alt.width());
861  yAssert(height()==alt.height());
862  if (getPixelCode()==alt.getPixelCode()) {
863  if (getQuantum()==alt.getQuantum()) {
865  yAssert(q1==q2);
866  }
867  }
868 
869  copyPixels(alt.getRawImage(),alt.getPixelCode(),
871  width(),height(),
872  getRawImageSize(),q1,q2,o1,o2);
873  }
874  return true;
875 }
876 
877 
878 void Image::setExternal(const void *data, size_t imgWidth, size_t imgHeight) {
879  if (imgQuantum==0) {
880  imgQuantum = 1;
881  }
882  (static_cast<ImageStorage*>(implementation))->_alloc_complete_extern(data,
883  imgWidth,
884  imgHeight,
885  getPixelCode(),
886  imgQuantum,
887  topIsLow);
888  synchronize();
889 }
890 
891 
892 bool Image::copy(const Image& alt, size_t w, size_t h) {
893  if (getPixelCode()==0) {
894  setPixelCode(alt.getPixelCode());
895  setQuantum(alt.getQuantum());
896  }
897  if (&alt==this) {
898  FlexImage img;
899  img.copy(alt);
900  return copy(img,w,h);
901  }
902 
903  if (getPixelCode()!=alt.getPixelCode()) {
904  FlexImage img;
905  img.setPixelCode(getPixelCode());
906  img.setQuantum(getQuantum());
907  img.copy(alt);
908  return copy(img,w,h);
909  }
910 
911  resize(w,h);
912  size_t d = getPixelSize();
913 
914  size_t nw = w;
915  size_t nh = h;
916  w = alt.width();
917  h = alt.height();
918 
919  float di = (static_cast<float>(h))/nh;
920  float dj = (static_cast<float>(w))/nw;
921 
922  for (size_t i=0; i<nh; i++)
923  {
924  auto i0 = static_cast<size_t>(di*i);
925  for (size_t j=0; j<nw; j++)
926  {
927  auto j0 = static_cast<size_t>(dj*j);
928  memcpy(getPixelAddress(j,i),
929  alt.getPixelAddress(j0,i0),
930  d);
931  }
932  }
933  return true;
934 }
yarp::sig::Image::setPixelCode
void setPixelCode(int imgPixelCode)
Definition: Image.cpp:504
IPL_BORDER_CONSTANT
#define IPL_BORDER_CONSTANT
Definition: IplImage.h:286
ImageStorage::_make_independent
void _make_independent()
Definition: Image.cpp:292
yarp::sig::Image::write
bool write(yarp::os::ConnectionWriter &connection) const override
Write image to a connection.
Definition: Image.cpp:772
VOCAB_PIXEL_RGB_INT
@ VOCAB_PIXEL_RGB_INT
Definition: Image.h:58
IPL_DATA_ORDER_PIXEL
#define IPL_DATA_ORDER_PIXEL
Definition: IplImage.h:70
yarp::os::ConnectionWriter::appendBlock
virtual void appendBlock(const char *data, size_t len)=0
Send a block of data to the network connection.
yarp::os::Portable
This is a base class for objects that can be both read from and be written to the YARP network.
Definition: Portable.h:29
ImageStorage::_alloc_extern
void _alloc_extern(const void *buf)
Definition: Image.cpp:188
VOCAB_PIXEL_RGB_FLOAT
@ VOCAB_PIXEL_RGB_FLOAT
Definition: Image.h:60
yarp::sig::ImageNetworkHeader
Byte order in image header for network transmission.
Definition: ImageNetworkHeader.h:33
yarp::sig::Image::setPixelSize
void setPixelSize(size_t imgPixelSize)
Definition: Image.cpp:496
pixelTypeIplParams::channelSeq
const char * channelSeq
Definition: Image.cpp:302
IPL_ALIGN_QWORD
#define IPL_ALIGN_QWORD
Definition: IplImage.h:82
deBayer_GRBG8_TO_RGB
bool deBayer_GRBG8_TO_RGB(yarp::sig::Image &source, yarp::sig::Image &dest, int pixelSize)
Definition: DeBayer.cpp:78
ImageNetworkHeader.h
yarp::sig
Signal processing.
Definition: Image.h:25
ImageStorage::extern_type_quantum
size_t extern_type_quantum
Definition: Image.cpp:78
VOCAB_PIXEL_RGB_SIGNED
@ VOCAB_PIXEL_RGB_SIGNED
Definition: Image.h:57
ImageStorage::_set_ipl_header
bool _set_ipl_header(size_t x, size_t y, int pixel_type, size_t quantum, bool topIsLow)
Definition: Image.cpp:337
ImageStorage::_alloc_complete_extern
void _alloc_complete_extern(const void *buf, size_t x, size_t y, int pixel_type, size_t quantum, bool topIsLow)
Definition: Image.cpp:370
iplDeallocateImage
void iplDeallocateImage(IplImage *image)
Definition: IplImage.cpp:731
ImageStorage::type_id
int type_id
Definition: Image.cpp:85
ConnectionWriter.h
yarp::sig::ImageNetworkHeader::depth
yarp::os::NetInt32 depth
Definition: ImageNetworkHeader.h:44
IPL_ORIGIN_TL
#define IPL_ORIGIN_TL
Definition: IplImage.h:73
yarp::sig::Image::zero
void zero()
Set all pixels to 0.
Definition: Image.cpp:459
yarp::sig::Image::operator=
Image & operator=(const Image &alt)
Assignment operator.
Definition: Image.cpp:833
VOCAB_PIXEL_ENCODING_BAYER_BGGR16
@ VOCAB_PIXEL_ENCODING_BAYER_BGGR16
Definition: Image.h:65
DeBayer.h
ImageStorage::_alloc_data
void _alloc_data()
Definition: Image.cpp:207
pixelTypeIplParams::colorModel
const char * colorModel
Definition: Image.cpp:301
iplPixelTypeMono
const pixelTypeIplParams iplPixelTypeMono
Definition: Image.cpp:305
yarp::sig::ImageNetworkHeader::width
yarp::os::NetInt32 width
Definition: ImageNetworkHeader.h:47
yarp::sig::Image::getQuantum
size_t getQuantum() const
The size of a row is constrained to be a multiple of the "quantum".
Definition: Image.h:186
yarp::sig::PixelMonoSigned
char PixelMonoSigned
Signed byte pixel type.
Definition: Image.h:555
ImageStorage::extern_type_id
int extern_type_id
Definition: Image.cpp:77
iplDeallocate
void iplDeallocate(IplImage *image, int flag)
Definition: IplImage.cpp:900
yarp::sig::PAD_BYTES
size_t PAD_BYTES(size_t len, size_t pad)
computes the padding of YARP images.
Definition: Image.h:36
yarp::sig::PixelBgr
Packed RGB pixel type, with pixels stored in reverse order.
Definition: Image.h:525
yarp::sig::PixelRgbSigned
Signed, packed RGB pixel type.
Definition: Image.h:562
yarp::sig::ImageNetworkHeader::setFromImage
void setFromImage(const Image &image)
Definition: ImageNetworkHeader.h:58
IPL_DEPTH_8S
#define IPL_DEPTH_8S
Definition: IplImage.h:66
yarp::sig::Image::copy
bool copy(const Image &alt)
Copy operator.
Definition: Image.cpp:842
yarp::sig::Image::~Image
~Image() override
Destructor.
Definition: Image.cpp:441
IPL_IMAGE_HEADER
#define IPL_IMAGE_HEADER
Definition: IplImage.h:300
yarp::sig::ImageNetworkHeader::id
yarp::os::NetInt32 id
Definition: ImageNetworkHeader.h:41
yarp::sig::PixelBgra
Packed BGRA pixel type.
Definition: Image.h:500
yarp::sig::PixelHsvFloat
Floating point HSV pixel type.
Definition: Image.h:623
ImageStorage::_alloc_complete
void _alloc_complete(size_t x, size_t y, int pixel_type, size_t quantum, bool topIsLow)
Definition: Image.cpp:280
ImageStorage::_free_complete
void _free_complete()
Definition: Image.cpp:262
ImageStorage::_pad_bytes
int _pad_bytes(size_t linesize, size_t align) const
Definition: Image.cpp:389
ImageStorage::resize
void resize(size_t x, size_t y, int pixel_type, size_t quantum, bool topIsLow)
Definition: Image.cpp:144
yarp::sig::Image::wrapIplImage
void wrapIplImage(void *iplImage)
Act as a wrapper around an IPL/OpenCV image.
Definition: Image.cpp:561
yarp::sig::Image::read
bool read(yarp::os::ConnectionReader &connection) override
Read image from a connection.
Definition: Image.cpp:665
yarp::sig::Image::getPixelSize
virtual size_t getPixelSize() const
Gets pixel size in memory in bytes.
Definition: Image.cpp:449
pixelTypeIplParams
Definition: Image.cpp:298
yarp::sig::Image::getRawImageSize
size_t getRawImageSize() const
Access to the internal buffer size information (this is how much memory has been allocated for the im...
Definition: Image.cpp:543
VOCAB_PIXEL_ENCODING_BAYER_RGGB8
@ VOCAB_PIXEL_ENCODING_BAYER_RGGB8
Definition: Image.h:68
iplAllocateImage
void iplAllocateImage(IplImage *image, int doFill, int fillValue)
Definition: IplImage.cpp:661
yarp::sig::Image::Image
Image()
Default constructor.
Definition: Image.cpp:424
yarp::sig::Image::width
size_t width() const
Gets width of image in pixels.
Definition: Image.h:153
VOCAB_PIXEL_RGBA
@ VOCAB_PIXEL_RGBA
Definition: Image.h:51
yarp::sig::PixelRgbInt
Integer RGB pixel type.
Definition: Image.h:601
yarp::sig::Image::setExternal
void setExternal(const void *data, size_t imgWidth, size_t imgHeight)
Use this to wrap an external image.
Definition: Image.cpp:878
yarp::sig::Image::topIsLowIndex
bool topIsLowIndex() const
Definition: Image.h:340
yarp::os::Vocab::decode
std::string decode(NetInt32 code)
Convert a vocabulary identifier into a string.
Definition: Vocab.cpp:36
yarp::sig::FlexImage::setQuantum
void setQuantum(size_t imgQuantum)
Definition: Image.h:418
_IplImage::nChannels
int nChannels
Most of OpenCV functions support 1,2,3 or 4 channels.
Definition: IplImage.h:87
VOCAB_PIXEL_HSV_FLOAT
@ VOCAB_PIXEL_HSV_FLOAT
Definition: Image.h:61
Log.h
yarp::os::ConnectionWriter::isError
virtual bool isError() const =0
IPL_DEPTH_8U
#define IPL_DEPTH_8U
Definition: IplImage.h:62
ImageStorage::ImageStorage
ImageStorage(Image &owner)
Definition: Image.cpp:119
VOCAB_PIXEL_YUV_422
@ VOCAB_PIXEL_YUV_422
Definition: Image.h:72
YARP_FIXME_NOTIMPLEMENTED
#define YARP_FIXME_NOTIMPLEMENTED(what)
Definition: Log.h:310
yarp::sig::PixelMono
unsigned char PixelMono
Monochrome pixel type.
Definition: Image.h:436
ImageStorage
Definition: Image.cpp:73
ImageStorage::_alloc
void _alloc()
Definition: Image.cpp:171
yarp::sig::PixelFloat
float PixelFloat
Floating point pixel type.
Definition: Image.h:572
yarp::os::ConnectionWriter
An interface for writing to a network connection.
Definition: ConnectionWriter.h:40
VOCAB_PIXEL_YUV_420
@ VOCAB_PIXEL_YUV_420
Definition: Image.h:70
yarp::sig::FlexImage
Image class with user control of representation details.
Definition: Image.h:403
yarp::sig::ImageNetworkHeader::height
yarp::os::NetInt32 height
Definition: ImageNetworkHeader.h:48
iplPixelTypeMono16
const pixelTypeIplParams iplPixelTypeMono16
Definition: Image.cpp:306
VOCAB_PIXEL_ENCODING_BAYER_RGGB16
@ VOCAB_PIXEL_ENCODING_BAYER_RGGB16
Definition: Image.h:69
yarp::sig::Image::getPixelAddress
unsigned char * getPixelAddress(size_t x, size_t y) const
Get address of a pixel in memory.
Definition: Image.h:227
yarp::sig::FlexImage::setPixelCode
void setPixelCode(int imgPixelCode)
Definition: Image.h:406
IPL_DEPTH_32S
#define IPL_DEPTH_32S
Definition: IplImage.h:68
yarp::os::ConnectionReader::isError
virtual bool isError() const =0
yarp::sig::PixelInt
yarp::os::NetInt32 PixelInt
32-bit integer pixel type.
Definition: Image.h:446
VOCAB_PIXEL_YUV_444
@ VOCAB_PIXEL_YUV_444
Definition: Image.h:71
VOCAB_PIXEL_ENCODING_BAYER_GBRG16
@ VOCAB_PIXEL_ENCODING_BAYER_GBRG16
Definition: Image.h:67
VOCAB_PIXEL_BGRA
@ VOCAB_PIXEL_BGRA
Definition: Image.h:52
IPL_SIDE_ALL
#define IPL_SIDE_ALL
Definition: IplImage.h:296
readFromConnection
bool readFromConnection(Image &dest, ImageNetworkHeader &header, ConnectionReader &connection)
This helper function groups code to avoid duplication.
Definition: Image.cpp:48
yarp::sig::Image::resize
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:466
yarp::sig::Image::height
size_t height() const
Gets height of image in pixels.
Definition: Image.h:159
ImageStorage::Data
char ** Data
Definition: Image.cpp:76
yarp::os::ConnectionReader::convertTextMode
virtual bool convertTextMode()=0
Reads in a standard description in text mode, and converts it to a standard description in binary.
ImageStorage::GetPadding
int GetPadding() const
Definition: Image.cpp:113
deBayer_GRBG8_TO_BGR
bool deBayer_GRBG8_TO_BGR(yarp::sig::Image &source, yarp::sig::Image &dest, int pixelSize)
Definition: DeBayer.cpp:12
_IplImage::colorModel
char colorModel[4]
ignored by OpenCV
Definition: IplImage.h:91
yarp::sig::PixelHsv
Packed HSV (hue/saturation/value pixel type.
Definition: Image.h:545
pixelCode2iplParams
const std::map< int, pixelTypeIplParams > pixelCode2iplParams
Definition: Image.cpp:308
VOCAB_PIXEL_ENCODING_BAYER_GRBG16
@ VOCAB_PIXEL_ENCODING_BAYER_GRBG16
Definition: Image.h:63
ImageStorage::pImage
IplImage * pImage
Definition: Image.cpp:75
ImageStorage::owner
Image & owner
Definition: Image.cpp:83
IplImage.h
YARP_IMAGE_ALIGN
#define YARP_IMAGE_ALIGN
Definition: IplImage.h:316
ImageStorage::_free
void _free()
Definition: Image.cpp:238
VOCAB_PIXEL_ENCODING_BAYER_GBRG8
@ VOCAB_PIXEL_ENCODING_BAYER_GBRG8
Definition: Image.h:66
VOCAB_PIXEL_INVALID
@ VOCAB_PIXEL_INVALID
Definition: Image.h:47
_IplImage
Definition: IplImage.h:84
yarp::os::ConnectionWriter::convertTextMode
virtual bool convertTextMode()=0
Converts a standard description in binary into a textual description, if the connection is in text-mo...
VOCAB_PIXEL_MONO_SIGNED
@ VOCAB_PIXEL_MONO_SIGNED
Definition: Image.h:56
yarp::sig::Image::getIplImage
void * getIplImage()
Returns IPL/OpenCV view of image, if possible.
Definition: Image.cpp:553
isBayer8
bool isBayer8(int v)
Basic implementations of debayering functions.
Definition: DeBayer.h:22
Image.h
yarp::os::ConnectionReader
An interface for reading from a network connection.
Definition: ConnectionReader.h:40
_IplImage::width
int width
image width in pixels
Definition: IplImage.h:99
yarp::sig::PixelRgba
Packed RGBA pixel type.
Definition: Image.h:475
ImageStorage::quantum
size_t quantum
Definition: Image.cpp:79
IPL_DEPTH_16S
#define IPL_DEPTH_16S
Definition: IplImage.h:67
VOCAB_PIXEL_INT
@ VOCAB_PIXEL_INT
Definition: Image.h:53
yarp::sig::ImageNetworkHeader::quantum
yarp::os::NetInt32 quantum
Definition: ImageNetworkHeader.h:46
ImageStorage::getTypeId
int getTypeId()
ImageStorage::getTypeId.
Definition: Image.cpp:165
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::PixelRgbFloat
Floating point RGB pixel type.
Definition: Image.h:579
IPL_ORIGIN_BL
#define IPL_ORIGIN_BL
Definition: IplImage.h:74
yarp::sig::PixelRgb
Packed RGB pixel type.
Definition: Image.h:453
yarp::sig::PixelMono16
yarp::os::NetUint16 PixelMono16
16-bit monochrome pixel type.
Definition: Image.h:441
yarp::sig::Image
Base class for storing images.
Definition: Image.h:85
Vocab.h
ImageStorage::_free_data
void _free_data()
Definition: Image.cpp:256
VOCAB_PIXEL_RGB
@ VOCAB_PIXEL_RGB
Definition: Image.h:50
IPL_DEPTH_32F
#define IPL_DEPTH_32F
Definition: IplImage.h:64
ImageStorage::~ImageStorage
~ImageStorage()
Definition: Image.cpp:130
implementation
RandScalar * implementation(void *t)
Definition: RandnScalar.cpp:20
ImageStorage::topIsLow
bool topIsLow
Definition: Image.cpp:80
Time.h
yarp::os::ConnectionWriter::appendExternalBlock
virtual void appendExternalBlock(const char *data, size_t len)=0
Send a block of data to the network connection, without making a copy.
VOCAB_PIXEL_YUV_411
@ VOCAB_PIXEL_YUV_411
Definition: Image.h:73
iplAllocateImageFP
void iplAllocateImageFP(IplImage *image, int doFill, float fillValue)
Definition: IplImage.cpp:694
pixelTypeIplParams::depth
int depth
Definition: Image.cpp:300
ImageStorage::is_owner
int is_owner
Definition: Image.cpp:87
pixelTypeIplParams::nChannels
int nChannels
Definition: Image.cpp:299
yarp::os::ConnectionReader::expectBlock
virtual bool expectBlock(char *data, size_t len)=0
Read a block of data from the network connection.
isBayer16
bool isBayer16(int v)
Definition: DeBayer.h:33
IPL_DEPTH_16U
#define IPL_DEPTH_16U
Definition: IplImage.h:63
YarpVocabPixelTypesEnum
YarpVocabPixelTypesEnum
Definition: Image.h:46
VOCAB_PIXEL_ENCODING_BAYER_BGGR8
@ VOCAB_PIXEL_ENCODING_BAYER_BGGR8
Definition: Image.h:64
yAssert
#define yAssert(x)
Definition: Log.h:297
ImageStorage::_free_ipl_header
void _free_ipl_header()
Definition: Image.cpp:270
iplSetBorderMode
void iplSetBorderMode(IplImage *src, int mode, int border, int constVal)
Definition: IplImage.cpp:922
VOCAB_PIXEL_MONO16
@ VOCAB_PIXEL_MONO16
Definition: Image.h:49
VOCAB_PIXEL_BGR
@ VOCAB_PIXEL_BGR
Definition: Image.h:55
Bottle.h
yarp::sig::ImageNetworkHeader::imgSize
yarp::os::NetInt32 imgSize
Definition: ImageNetworkHeader.h:45
yarp::sig::Image::getRawImage
unsigned char * getRawImage() const
Access to the internal image buffer.
Definition: Image.cpp:534
iplCreateImageHeader
IplImage * iplCreateImageHeader(int nChannels, int alphaChannel, int depth, char *colorModel, char *channelSeq, int dataOrder, int origin, int align, int width, int height, IplROI *roi, IplImage *maskROI, void *imageId, IplTileInfo *tileInfo)
Definition: IplImage.cpp:786
VOCAB_PIXEL_HSV
@ VOCAB_PIXEL_HSV
Definition: Image.h:54
DBGPF1
#define DBGPF1
Definition: Image.cpp:36
ConnectionReader.h
VOCAB_PIXEL_ENCODING_BAYER_GRBG8
@ VOCAB_PIXEL_ENCODING_BAYER_GRBG8
Definition: Image.h:62
VOCAB_PIXEL_MONO_FLOAT
@ VOCAB_PIXEL_MONO_FLOAT
Definition: Image.h:59
yarp::sig::Image::setQuantum
void setQuantum(size_t imgQuantum)
Definition: Image.cpp:510
yarp::sig::Image::getPixelCode
virtual int getPixelCode() const
Gets pixel type identifier.
Definition: Image.cpp:454