YARP  2.3.70.2
Yet Another Robot Platform
Image.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007 RobotCub Consortium
3  * Authors: Paul Fitzpatrick, Giorgio Metta
4  * CopyPolicy: Released under the terms of the LGPLv2.1 or later, see LGPL.TXT
5  */
6 
7 
8 /*
9  This file is in a pretty hacky state. Sorry!
10 
11 */
12 
13 #include <yarp/sig/IplImage.h>
14 
15 #include <yarp/os/Log.h>
16 #include <yarp/sig/Image.h>
18 
19 #include <yarp/os/Bottle.h>
20 #include <yarp/os/Vocab.h>
21 #include <yarp/os/ConstString.h>
22 #include <yarp/os/Time.h>
23 
24 #include <yarp/sig/impl/DeBayer.h>
25 
26 #include <cstdio>
27 #include <cstring>
28 
29 using namespace yarp::sig;
30 using namespace yarp::os;
31 
32 #define DBGPF1 if (0)
33 
34 //inline int PAD_BYTES (int len, int pad)
35 //{
36 // const int rem = len % pad;
37 // return (rem != 0) ? (pad - rem) : rem;
38 //}
39 
45 {
46  dest.resize(header.width, header.height);
47  unsigned char *mem = dest.getRawImage();
48  int allocatedBytes = dest.getRawImageSize();
49  yAssert(mem != NULL);
50  //this check is redundant with assertion, I would remove it
51  if (dest.getRawImageSize() != header.imgSize) {
52  printf("There is a problem reading an image\n");
53  printf("incoming: width %d, height %d, code %d, quantum %d, size %d\n",
54  (int)header.width, (int)header.height,
55  (int)header.id,
56  (int)header.quantum, (int)header.imgSize);
57  printf("my space: width %d, height %d, code %d, quantum %d, size %d\n",
58  dest.width(), dest.height(), dest.getPixelCode(), dest.getQuantum(), allocatedBytes);
59  }
60  yAssert(allocatedBytes == header.imgSize);
61  bool ok = connection.expectBlock((char *)mem, allocatedBytes);
62  return (!connection.isError() && ok);
63 }
64 
65 
66 
67 class ImageStorage {
68 public:
70  char **Data; // this is not IPL. it's char to maintain IPL compatibility
73  int quantum;
74  bool topIsLow;
75 
76 protected:
78 
79  int type_id;
80 
81  int is_owner;
82 
83  // ipl allocation is done in two steps.
84  // _alloc allocates the actual ipl pointer.
85  // _alloc_data allocates the image array and data.
86  // memory is allocated in a single chunk. Row ptrs are then
87  // made to point appropriately. This is compatible with IPL and
88  // SOMEONE says it's more efficient on NT.
89  void _alloc (void);
90  void _alloc_extern (const void *buf);
91  void _alloc_data (void);
92  void _free (void);
93  void _free_data (void);
94 
95  void _make_independent();
96  void _set_ipl_header(int x, int y, int pixel_type, int quantum,
97  bool topIsLow);
98  void _free_ipl_header();
99  void _alloc_complete(int x, int y, int pixel_type, int quantum,
100  bool topIsLow);
101  void _free_complete();
102 
103 
104  // computes the # of padding bytes. These are always at the end of the row.
105  int _pad_bytes (int linesize, int align) const;
106 
107  inline int GetPadding() const {
108  return _pad_bytes (pImage->width * pImage->nChannels,
110  }
111 
112 public:
113  ImageStorage(Image& owner) : owner(owner) {
114  type_id = 0;
115  pImage = NULL;
116  Data = NULL;
117  is_owner = 1;
118  quantum = 0;
119  topIsLow = true;
120  extern_type_id = 0;
121  extern_type_quantum = -1;
122  }
123 
125  _free_complete();
126  }
127 
128  void resize(int x, int y, int pixel_type,
129  int pixel_size, int quantum, bool topIsLow);
130 
131  void _alloc_complete_extern(const void *buf, int x, int y, int pixel_type,
132  int quantum, bool topIsLow);
133 
134 };
135 
136 
137 void ImageStorage::resize(int x, int y, int pixel_type,
138  int pixel_size, int quantum, bool topIsLow) {
139  int need_recreation = 1;
140 
141  if (quantum==0) {
142  quantum = YARP_IMAGE_ALIGN;
143  }
144 
145  if (need_recreation) {
146  _free_complete();
147  DBGPF1 printf("HIT recreation for %ld %ld: %d %d %d\n", (long int) this, (long int) pImage, x, y, pixel_type);
148  _alloc_complete (x, y, pixel_type, quantum, topIsLow);
149  }
150  extern_type_id = pixel_type;
151  extern_type_quantum = quantum;
152 }
153 
154 
155 
156 
157 // allocates an empty image.
158 void ImageStorage::_alloc (void) {
159  yAssert(pImage != NULL);
160 
161  if (pImage != NULL)
162  if (pImage->imageData != NULL)
163  _free(); // was iplDeallocateImage(pImage); but that won't work with refs
164 
165  if ( (type_id == VOCAB_PIXEL_MONO_FLOAT) || (type_id == VOCAB_PIXEL_RGB_FLOAT) ||
166  (type_id == VOCAB_PIXEL_HSV_FLOAT) )
167  iplAllocateImageFP(pImage, 0, 0);
168  else
169  iplAllocateImage (pImage, 0, 0);
170 
171  iplSetBorderMode (pImage, IPL_BORDER_CONSTANT, IPL_SIDE_ALL, 0);
172 }
173 
174 // installs an external buffer as the image data
175 void ImageStorage::_alloc_extern (const void *buf)
176 {
177  yAssert(pImage != NULL);
178  yAssert(Data==NULL);
179 
180  if (pImage != NULL)
181  if (pImage->imageData != NULL)
182  iplDeallocateImage (pImage);
183 
184  //iplAllocateImage (pImage, 0, 0);
185  pImage->imageData = (char*)buf;
186  // probably need to do more for real IPL
187 
188  //iplSetBorderMode (pImage, IPL_BORDER_CONSTANT, IPL_SIDE_ALL, 0);
189 }
190 
191 // allocates the Data pointer.
193 {
194  DBGPF1 printf("alloc_data1\n"), fflush(stdout);
195  yAssert(pImage != NULL);
196 
197  yAssert(Data==NULL);
198 
199  char **ptr = new char *[pImage->height];
200 
201  Data = ptr;
202 
203  yAssert(Data != NULL);
204 
205  yAssert(pImage->imageData != NULL);
206 
207  int height = pImage->height;
208 
209  char * DataArea = pImage->imageData;
210 
211  for (int r = 0; r < height; r++)
212  {
213  if (topIsLow) {
214  Data[r] = DataArea;
215  } else {
216  Data[height-r-1] = DataArea;
217  }
218  DataArea += pImage->widthStep;
219  }
220  DBGPF1 printf("alloc_data4\n");
221 }
222 
224 {
225  if (pImage != NULL)
226  if (pImage->imageData != NULL)
227  {
228  if (is_owner)
229  {
230  iplDeallocateImage (pImage);
231  if (Data!=NULL)
232  {
233  delete[] Data;
234  }
235  }
236  else
237  {
238  if (Data!=NULL)
239  {
240  delete[] Data;
241  }
242  }
243 
244  is_owner = 1;
245  Data = NULL;
246  pImage->imageData = NULL;
247  }
248 }
249 
251 {
252  yAssert(Data==NULL); // Now always free Data at same time
253 }
254 
255 
257 {
258  _free();
259  _free_data();
260  _free_ipl_header();
261 }
262 
263 
265 {
266  if (pImage!=NULL)
267  {
268  iplDeallocate (pImage, IPL_IMAGE_HEADER);
269  }
270  pImage = NULL;
271 }
272 
273 
274 void ImageStorage::_alloc_complete(int x, int y, int pixel_type, int quantum,
275  bool topIsLow)
276 {
277  _make_independent();
278  _free_complete();
279  _set_ipl_header(x, y, pixel_type, quantum, topIsLow);
280  _alloc ();
281  _alloc_data ();
282 }
283 
284 
285 
287 {
288  // actually I think this isn't really needed -paulfitz
289 }
290 
291 
292 void ImageStorage::_set_ipl_header(int x, int y, int pixel_type, int quantum,
293  bool topIsLow)
294 {
295  if (quantum==0) {
296  quantum = IPL_ALIGN_QWORD;
297  }
298  int origin = topIsLow?IPL_ORIGIN_TL:IPL_ORIGIN_BL;
299  int implemented_yet = 1;
300  // used to allocate the ipl header.
301  switch (pixel_type)
302  {
303  case VOCAB_PIXEL_MONO:
304  pImage = iplCreateImageHeader(
305  1,
306  0,
307  IPL_DEPTH_8U,
308  (char *)"GRAY",
309  (char *)"GRAY",
311  origin,
312  quantum,
313  x,
314  y,
315  NULL,
316  NULL,
317  NULL,
318  NULL);
319  DBGPF1 printf("Set pImage to %ld\n", (long int) pImage);
320  DBGPF1 printf("Set init h to %ld\n", (long int) pImage->height);
321  break;
322 
323  case VOCAB_PIXEL_MONO16:
324  pImage = iplCreateImageHeader(
325  1,
326  0,
328  (char *)"GRAY",
329  (char *)"GRAY",
331  origin,
332  quantum,
333  x,
334  y,
335  NULL,
336  NULL,
337  NULL,
338  NULL);
339  break;
340 
341  case VOCAB_PIXEL_RGB:
342  pImage = iplCreateImageHeader(
343  3,
344  0,
345  IPL_DEPTH_8U,
346  (char *)"RGB",
347  (char *)"RGB",
349  origin,
350  quantum,
351  x,
352  y,
353  NULL,
354  NULL,
355  NULL,
356  NULL);
357  break;
358 
359  case VOCAB_PIXEL_RGBA:
360  pImage = iplCreateImageHeader(
361  4,
362  0,
363  IPL_DEPTH_8U,
364  (char *)"RGBA",
365  (char *)"RGBA",
367  origin,
368  quantum,
369  x,
370  y,
371  NULL,
372  NULL,
373  NULL,
374  NULL);
375  break;
376 
377  case VOCAB_PIXEL_BGRA:
378  pImage = iplCreateImageHeader(
379  4,
380  0,
381  IPL_DEPTH_8U,
382  (char *)"BGRA",
383  (char *)"BGRA",
385  origin,
386  quantum,
387  x,
388  y,
389  NULL,
390  NULL,
391  NULL,
392  NULL);
393  break;
394 
395  case VOCAB_PIXEL_RGB_INT:
396  pImage = iplCreateImageHeader(
397  3,
398  0,
400  (char *)"RGB",
401  (char *)"RGB",
403  origin,
404  quantum,
405  x,
406  y,
407  NULL,
408  NULL,
409  NULL,
410  NULL);
411  break;
412 
413  case VOCAB_PIXEL_HSV:
414  pImage = iplCreateImageHeader(
415  3,
416  0,
417  IPL_DEPTH_8U,
418  (char *)"HSV",
419  (char *)"HSV",
421  origin,
422  quantum,
423  x,
424  y,
425  NULL,
426  NULL,
427  NULL,
428  NULL);
429  break;
430 
431  case VOCAB_PIXEL_BGR:
432  pImage = iplCreateImageHeader(
433  3,
434  0,
435  IPL_DEPTH_8U,
436  (char *)"RGB",
437  (char *)"BGR",
439  origin,
440  quantum,
441  x,
442  y,
443  NULL,
444  NULL,
445  NULL,
446  NULL);
447  break;
448 
450  pImage = iplCreateImageHeader(
451  1,
452  0,
453  IPL_DEPTH_8S,
454  (char *)"GRAY",
455  (char *)"GRAY",
457  origin,
458  quantum,
459  x,
460  y,
461  NULL,
462  NULL,
463  NULL,
464  NULL);
465  break;
466 
468  yAssert(implemented_yet == 0);
469  break;
470 
472  pImage = iplCreateImageHeader(
473  1,
474  0,
476  (char *)"GRAY",
477  (char *)"GRAY",
479  origin,
480  quantum,
481  x,
482  y,
483  NULL,
484  NULL,
485  NULL,
486  NULL);
487  break;
488 
490  pImage = iplCreateImageHeader(
491  3,
492  0,
494  (char *)"RGB",
495  (char *)"RGB",
497  origin,
498  quantum,
499  x,
500  y,
501  NULL,
502  NULL,
503  NULL,
504  NULL);
505  //yAssert(implemented_yet == 0);
506  break;
507 
509  yAssert(implemented_yet == 0);
510  break;
511 
512  case VOCAB_PIXEL_INT:
513  pImage = iplCreateImageHeader(
514  1,
515  0,
517  (char *)"GRAY",
518  (char *)"GRAY",
520  origin,
521  quantum,
522  x,
523  y,
524  NULL,
525  NULL,
526  NULL,
527  NULL);
528  break;
529 
530  case VOCAB_PIXEL_INVALID:
531  // not a type!
532  printf ("*** Trying to allocate an invalid pixel type image\n");
533  std::exit(1);
534  break;
535 
536  case -2:
537  pImage = iplCreateImageHeader(
538  1,
539  0,
541  (char *)"GRAY",
542  (char *)"GRAY",
544  origin,
545  quantum,
546  x,
547  y,
548  NULL,
549  NULL,
550  NULL,
551  NULL);
552  break;
553 
554  case -4:
555  pImage = iplCreateImageHeader(
556  1,
557  0,
559  (char *)"GRAY",
560  (char *)"GRAY",
562  origin,
563  quantum,
564  x,
565  y,
566  NULL,
567  NULL,
568  NULL,
569  NULL);
570  break;
571 
572  default:
573  // unknown pixel type. Should revert to a non-IPL mode... how?
574  yAssert(implemented_yet == 0);
575  break;
576  }
577 
578  type_id = pixel_type;
579  this->quantum = quantum;
580  this->topIsLow = topIsLow;
581 }
582 
583 void ImageStorage::_alloc_complete_extern(const void *buf, int x, int y, int pixel_type, int quantum, bool topIsLow)
584 {
585  if (quantum==0) {
586  quantum = 1;
587  }
588  this->quantum = quantum;
589  this->topIsLow = topIsLow;
590 
591  _make_independent();
592  _free_complete();
593  _set_ipl_header(x, y, pixel_type, quantum, topIsLow);
594  Data = NULL;
595  _alloc_extern (buf);
596  _alloc_data ();
597  is_owner = 0;
598 }
599 
600 
601 
602 int ImageStorage::_pad_bytes (int linesize, int align) const
603 {
604  return yarp::sig::PAD_BYTES (linesize, align);
605 }
606 
607 
608 
609 
610 
611 
612 
613 
615  initialize();
616 }
617 
619  implementation = NULL;
620  data = NULL;
621  imgWidth = imgHeight = 0;
622  imgPixelSize = imgRowSize = 0;
623  imgPixelCode = 0;
624  imgQuantum = 0;
625  topIsLow = true;
626  implementation = new ImageStorage(*this);
627  yAssert(implementation!=NULL);
628 }
629 
630 
632  if (implementation!=NULL) {
633  delete (ImageStorage*)implementation;
634  implementation = NULL;
635  }
636 }
637 
638 
639 int Image::getPixelSize() const {
640  return imgPixelSize;
641 }
642 
643 
644 int Image::getPixelCode() const {
645  return imgPixelCode;
646 }
647 
648 
649 void Image::zero() {
650  if (getRawImage()!=NULL) {
651  memset(getRawImage(),0,getRawImageSize());
652  }
653 }
654 
655 
656 void Image::resize(int imgWidth, int imgHeight) {
657  yAssert(imgWidth>=0 && imgHeight>=0);
658 
659  int code = getPixelCode();
660  int size = getPixelSize();
661  bool change = false;
662  if (code!=imgPixelCode) {
663  imgPixelCode = code;
664  change = true;
665  }
666  if (imgPixelCode!=((ImageStorage*)implementation)->extern_type_id) {
667  change = true;
668  }
669  if (imgQuantum!=((ImageStorage*)implementation)->extern_type_quantum) {
670  change = true;
671  }
672  if (size!=imgPixelSize) {
673  imgPixelSize = size;
674  change=true;
675  }
676  if (imgWidth!=width()||imgHeight!=height()) {
677  change = true;
678  }
679 
680  if (change) {
681  ((ImageStorage*)implementation)->resize(imgWidth,imgHeight,
682  imgPixelCode,
683  imgPixelSize,
684  imgQuantum,
685  topIsLow);
686  synchronize();
687  //printf("CHANGE! %ld\n", (long int)(this));
688  }
689 }
690 
691 
692 void Image::setPixelCode(int imgPixelCode) {
693  this->imgPixelCode = imgPixelCode;
694 }
695 
696 
697 void Image::setPixelSize(int imgPixelSize) {
698  this->imgPixelSize = imgPixelSize;
699 }
700 
701 
702 void Image::setQuantum(int imgQuantum) {
703  this->imgQuantum = imgQuantum;
704 }
705 
706 
709  yAssert(impl!=NULL);
710  if (impl->pImage!=NULL) {
711  imgWidth = impl->pImage->width;
712  imgHeight = impl->pImage->height;
713  data = impl->Data;
714  imgQuantum = impl->quantum;
715  imgRowSize = impl->pImage->widthStep;
716  } else {
717  data = NULL;
718  imgWidth = imgHeight = 0;
719  }
720  imgPixelSize = getPixelSize();
721  imgPixelCode = getPixelCode();
722 }
723 
724 
725 unsigned char *Image::getRawImage() const {
727  yAssert(impl!=NULL);
728  if (impl->pImage!=NULL) {
729  return (unsigned char *)impl->pImage->imageData;
730  }
731  return NULL;
732 }
733 
736  yAssert(impl!=NULL);
737  if (impl->pImage!=NULL) {
738  return impl->pImage->imageSize;
739  }
740  return 0;
741 }
742 
744  return ((ImageStorage*)implementation)->pImage;
745 }
746 
747 const void *Image::getIplImage() const {
748  return ((const ImageStorage*)implementation)->pImage;
749 }
750 
751 void Image::wrapIplImage(void *iplImage) {
752  yAssert(iplImage!=NULL);
753  IplImage *p = (IplImage *)iplImage;
754  ConstString str = p->colorModel;
755  int code = -1;
756  int color_code = -1;
757  if (str=="rgb"||str=="RGB"||
758  str=="bgr"||str=="BGR"||
759  str=="gray"||str=="GRAY"||
760  str=="graygray"||str=="GRAYGRAY") {
761  str = p->channelSeq;
762  if (str=="rgb"||str=="RGB") {
763  color_code = VOCAB_PIXEL_RGB;
764  } else if (str=="bgr"||str=="BGR") {
765  color_code = VOCAB_PIXEL_BGR;
766  } else if (str=="gray"||str=="GRAY"||
767  str=="graygray"||str=="GRAYGRAY") {
768  color_code = VOCAB_PIXEL_MONO;
769  } else {
770  printf("specific IPL RGB order (%s) is not yet supported\n",
771  str.c_str());
772  printf("Try RGB, BGR, or \n");
773  printf("Or fix code at %s line %d\n",__FILE__,__LINE__);
774  std::exit(1);
775  }
776  }
777 
778  // Type translation is approximate. Patches welcome to flesh out
779  // the types available.
780  if (p->depth == IPL_DEPTH_8U) {
781  code = color_code;
782  } else if (p->depth == IPL_DEPTH_8S) {
783  switch (color_code) {
784  case VOCAB_PIXEL_MONO:
786  break;
787  case VOCAB_PIXEL_RGB:
788  code = VOCAB_PIXEL_RGB_SIGNED;
789  break;
790  case VOCAB_PIXEL_BGR:
791  code = color_code; // nothing better available
792  break;
793  }
794  } else if (p->depth == IPL_DEPTH_16U || p->depth == IPL_DEPTH_16S) {
795  switch (color_code) {
796  case VOCAB_PIXEL_MONO:
797  code = VOCAB_PIXEL_MONO16;
798  break;
799  case VOCAB_PIXEL_RGB:
800  case VOCAB_PIXEL_BGR:
801  fprintf(stderr,"No translation currently available for this pixel type\n");
802  std::exit(1);
803  break;
804  }
805  } else if (p->depth == IPL_DEPTH_32S) {
806  switch (color_code) {
807  case VOCAB_PIXEL_MONO:
808  code = VOCAB_PIXEL_INT;
809  break;
810  case VOCAB_PIXEL_RGB:
811  case VOCAB_PIXEL_BGR:
812  code = VOCAB_PIXEL_RGB_INT;
813  break;
814  }
815  } else if (p->depth == IPL_DEPTH_32F) {
816  switch (color_code) {
817  case VOCAB_PIXEL_MONO:
818  code = VOCAB_PIXEL_MONO_FLOAT;
819  break;
820  case VOCAB_PIXEL_RGB:
821  case VOCAB_PIXEL_BGR:
822  code = VOCAB_PIXEL_RGB_FLOAT;
823  break;
824  }
825  }
826 
827  if (code==-1) {
828  fprintf(stderr,"IPL pixel type / depth combination is not yet supported\n");
829  fprintf(stderr,"Please email a YARP developer to complain, quoting this:\n");
830  fprintf(stderr," %s:%d\n", __FILE__, __LINE__);
831  }
832 
833  if (getPixelCode()!=code && getPixelCode()!=-1) {
834  printf("your specific IPL format (%s depth %d -> %s) does not match your YARP format (%s)\n",
835  str.c_str(),
836  p->depth,
837  Vocab::decode(code).c_str(),
838  Vocab::decode(getPixelCode()).c_str());
839  printf("Making a copy instead of just wrapping...\n");
840  FlexImage img;
841  img.setQuantum(p->align);
842  img.setPixelCode(code);
843  img.setExternal(p->imageData,p->width,p->height);
844  copy(img);
845  } else {
846  setQuantum(p->align);
847  setPixelCode(code);
848  setExternal(p->imageData,p->width,p->height);
849  }
850 }
851 
852 
853 
855 
856  // auto-convert text mode interaction
857  connection.convertTextMode();
858 
860 
861  bool ok = connection.expectBlock((char*)&header,sizeof(header));
862  if (!ok) return false;
863 
864  //first check that the received image size is reasonable
865  if (header.width == 0 || header.height == 0)
866  {
867  // I maintain the prevous logic, although we should probably return false
868  return !connection.isError();
869  }
870 
871  imgPixelCode = header.id;
872 
873  int q = getQuantum();
874  if (q==0) {
875  //q = YARP_IMAGE_ALIGN;
876  setQuantum(header.quantum);
877  q = getQuantum();
878  }
879  if (q!=header.quantum) {
880  if ((header.depth*header.width)%header.quantum==0 &&
881  (header.depth*header.width)%q==0) {
882  header.quantum = q;
883  }
884  }
885 
886  // handle easy case, received and current image are compatible, no conversion needed
887  if (getPixelCode() == header.id && q == header.quantum)
888  {
889  return readFromConnection(*this, header, connection);
890  }
891 
892  // image is bayer 8 bits, current image is MONO, copy as is (keep raw format)
893  if (getPixelCode() == VOCAB_PIXEL_MONO && isBayer8(header.id))
894  {
895  return readFromConnection(*this, header, connection);
896  }
897  // image is bayer 16 bits, current image is MONO16, copy as is (keep raw format)
898  if (getPixelCode() == VOCAB_PIXEL_MONO16 && isBayer16(header.id))
899  {
900  return readFromConnection(*this, header, connection);
901  }
902 
904  // Received and current images are binary incompatible do our best to convert
905  //
906 
907  // handle here all bayer encoding 8 bits
908  if (isBayer8(header.id))
909  {
910  FlexImage flex;
912  flex.setQuantum(header.quantum);
913 
914  bool ok = readFromConnection(flex, header, connection);
915  if (!ok)
916  return false;
917 
918  if (getPixelCode() == VOCAB_PIXEL_BGR && header.id==VOCAB_PIXEL_ENCODING_BAYER_GRBG8)
919  return deBayer_GRBG8_TO_BGR(flex, *this, 3);
920  else if (getPixelCode() == VOCAB_PIXEL_BGRA && header.id == VOCAB_PIXEL_ENCODING_BAYER_GRBG8)
921  return deBayer_GRBG8_TO_BGR(flex, *this, 4);
922  if (getPixelCode() == VOCAB_PIXEL_RGB && header.id==VOCAB_PIXEL_ENCODING_BAYER_GRBG8)
923  return deBayer_GRBG8_TO_RGB(flex, *this, 3);
924  if (getPixelCode() == VOCAB_PIXEL_RGBA && header.id == VOCAB_PIXEL_ENCODING_BAYER_GRBG8)
925  return deBayer_GRBG8_TO_RGB(flex, *this, 4);
926  else
927  {
928  YARP_FIXME_NOTIMPLEMENTED("Conversion from bayer encoding not yet implemented\n");
929  return false;
930  }
931  }
932 
933  // handle here all bayer encodings 16 bits
934  if (isBayer16(header.id))
935  {
936  // as bayer16 seems unlikely we defer implementation for later
937  YARP_FIXME_NOTIMPLEMENTED("Conversion from bayer encoding 16 bits not yet implemented\n");
938  return false;
939  }
940 
941  // Received image has valid YARP pixels and can be converted using Image primitives
942  // prepare a FlexImage, set it to be compatible with the received image
943  // read new image into FlexImage then copy from it.
944  FlexImage flex;
945  flex.setPixelCode(header.id);
946  flex.setQuantum(header.quantum);
947  ok = readFromConnection(flex, header, connection);
948  if (ok)
949  copy(flex);
950 
951  return ok;
952 }
953 
954 
957  header.setFromImage(*this);
958  /*
959  header.listTag = BOTTLE_TAG_LIST;
960  header.listLen = 4;
961  header.paramNameTag = BOTTLE_TAG_VOCAB;
962  header.paramName = VOCAB3('m','a','t');
963  header.paramIdTag = BOTTLE_TAG_VOCAB;
964  header.id = getPixelCode();
965  header.paramListTag = BOTTLE_TAG_LIST + BOTTLE_TAG_INT;
966  header.paramListLen = 5;
967  header.depth = getPixelSize();
968  header.imgSize = getRawImageSize();
969  header.quantum = getQuantum();
970  header.width = width();
971  header.height = height();
972  header.paramBlobTag = BOTTLE_TAG_BLOB;
973  header.paramBlobLen = getRawImageSize();
974  */
975 
976  connection.appendBlock((char*)&header,sizeof(header));
977  unsigned char *mem = getRawImage();
978  if (header.width!=0&&header.height!=0) {
979  yAssert(mem!=NULL);
980 
981  // Note use of external block.
982  // Implies care needed about ownership.
983  connection.appendExternalBlock((char *)mem,header.imgSize);
984  }
985 
986  // if someone is foolish enough to connect in text mode,
987  // let them see something readable.
988  connection.convertTextMode();
989 
990  return !connection.isError();
991 }
992 
993 
994 Image::Image(const Image& alt) : Portable() {
995  initialize();
996  copy(alt);
997 }
998 
999 
1000 const Image& Image::operator=(const Image& alt) {
1001  copy(alt);
1002  return *this;
1003 }
1004 
1005 
1006 bool Image::copy(const Image& alt) {
1007  bool ok = false;
1008  int myCode = getPixelCode();
1009  if (myCode==0) {
1010  setPixelCode(alt.getPixelCode());
1011  setPixelSize(alt.getPixelSize());
1012  setQuantum(alt.getQuantum());
1013  }
1014  resize(alt.width(),alt.height());
1015  int q1 = alt.getQuantum();
1016  int q2 = getQuantum();
1017  if (q1==0) { q1 = YARP_IMAGE_ALIGN; }
1018  if (q2==0) { q2 = YARP_IMAGE_ALIGN; }
1019 
1020  bool o1 = alt.topIsLowIndex();
1021  bool o2 = topIsLowIndex();
1022 
1023  yAssert(width()==alt.width());
1024  yAssert(height()==alt.height());
1025  if (getPixelCode()==alt.getPixelCode()) {
1026  if (getQuantum()==alt.getQuantum()) {
1028  yAssert(q1==q2);
1029  }
1030  }
1031  copyPixels(alt.getRawImage(),alt.getPixelCode(),
1033  width(),height(),
1034  getRawImageSize(),q1,q2,o1,o2);
1035  ok = true;
1036  return ok;
1037 }
1038 
1039 
1040 void Image::setExternal(const void *data, int imgWidth, int imgHeight) {
1041  if (imgQuantum==0) {
1042  imgQuantum = 1;
1043  }
1044  ((ImageStorage*)implementation)->_alloc_complete_extern(data,
1045  imgWidth,
1046  imgHeight,
1047  getPixelCode(),
1048  imgQuantum,
1049  topIsLow);
1050  synchronize();
1051 }
1052 
1053 
1054 bool Image::copy(const Image& alt, int w, int h) {
1055  if (getPixelCode()==0) {
1056  setPixelCode(alt.getPixelCode());
1057  setPixelSize(alt.getPixelSize());
1058  setQuantum(alt.getQuantum());
1059  }
1060  if (&alt==this) {
1061  FlexImage img;
1062  img.copy(alt);
1063  return copy(img,w,h);
1064  }
1065 
1066  if (getPixelCode()!=alt.getPixelCode()) {
1067  FlexImage img;
1068  img.setPixelCode(getPixelCode());
1069  img.setPixelSize(getPixelSize());
1070  img.setQuantum(getQuantum());
1071  img.copy(alt);
1072  return copy(img,w,h);
1073  }
1074 
1075  resize(w,h);
1076  int d = getPixelSize();
1077 
1078  int nw = w;
1079  int nh = h;
1080  w = alt.width();
1081  h = alt.height();
1082 
1083  float di = ((float)h)/nh;
1084  float dj = ((float)w)/nw;
1085 
1086  for (int i=0; i<nh; i++)
1087  {
1088  int i0 = (int)(di*i);
1089  for (int j=0; j<nw; j++)
1090  {
1091  int j0 = (int)(dj*j);
1092  memcpy(getPixelAddress(j,i),
1093  alt.getPixelAddress(j0,i0),
1094  d);
1095  }
1096  }
1097  return true;
1098 }
#define IPL_SIDE_ALL
Definition: IplImage.h:342
int height
image height in pixels
Definition: IplImage.h:145
#define IPL_ORIGIN_BL
Definition: IplImage.h:119
char channelSeq[4]
ignored by OpenCV
Definition: IplImage.h:137
int extern_type_id
Definition: Image.cpp:71
virtual void appendExternalBlock(const char *data, size_t len)=0
Send a block of data to the network connection, without making a copy.
unsigned char * getRawImage() const
Access to the internal image buffer.
Definition: Image.cpp:725
Byte order in image header for network transmission.
int align
Alignment of image rows (4 or 8).
Definition: IplImage.h:142
char ** Data
Definition: Image.cpp:70
#define DBGPF1
Definition: Image.cpp:32
bool copy(const Image &alt)
Copy operator.
Definition: Image.cpp:1006
void zero()
Set all pixels to 0.
Definition: Image.cpp:649
void setPixelSize(int imgPixelSize)
Definition: Image.h:348
virtual bool isError()=0
void synchronize()
Definition: Image.cpp:707
void _make_independent()
Definition: Image.cpp:286
ImageStorage(Image &owner)
Definition: Image.cpp:113
#define YARP_FIXME_NOTIMPLEMENTED(what)
Definition: Log.h:120
virtual ~Image()
Destructor.
Definition: Image.cpp:631
#define IPL_ALIGN_QWORD
Definition: IplImage.h:127
#define IPL_DEPTH_16S
Definition: IplImage.h:112
virtual void appendBlock(const char *data, size_t len)=0
Send a block of data to the network connection.
This is a base class for objects that can be both read from and be written to the YARP network...
Definition: Portable.h:26
BlobNetworkHeader header
Definition: TcpRosStream.h:38
~ImageStorage()
Definition: Image.cpp:124
void _free_data(void)
Definition: Image.cpp:250
bool topIsLowIndex() const
Definition: Image.h:283
int width() const
Gets width of image in pixels.
Definition: Image.h:101
void _free_ipl_header()
Definition: Image.cpp:264
void setFromImage(const Image &image)
#define IPL_DEPTH_8U
Definition: IplImage.h:107
char ** data
Definition: Image.h:324
void wrapIplImage(void *iplImage)
Act as a wrapper around an IPL/OpenCV image.
Definition: Image.cpp:751
* dest
Definition: ImageCopy.cpp:72
int type_id
Definition: Image.cpp:79
void _free_complete()
Definition: Image.cpp:256
void _alloc_data(void)
Definition: Image.cpp:192
char * imageData
pointer to aligned image data
Definition: IplImage.h:153
A string with almost the same api as std::string.
Definition: ConstString.h:44
virtual bool convertTextMode()=0
Reads in a standard description in text mode, and converts it to a standard description in binary...
Image()
Default constructor.
Definition: Image.cpp:614
int imgQuantum
Definition: Image.h:321
#define IPL_DEPTH_32S
Definition: IplImage.h:113
int extern_type_quantum
Definition: Image.cpp:72
void setPixelSize(int imgPixelSize)
Definition: Image.cpp:697
void resize(int imgWidth, int imgHeight)
Reallocate an image to be of a desired size, throwing away its current contents.
Definition: Image.cpp:656
#define IPL_DEPTH_32F
Definition: IplImage.h:109
void setPixelCode(int imgPixelCode)
Definition: Image.h:344
Image class with user control of representation details.
Definition: Image.h:341
void exit(int exit_code)
Portable wrapper for the exit() function.
Definition: Os.cpp:40
Base class for storing images.
Definition: Image.h:48
void copyPixels(const unsigned char *src, int id1, unsigned char *dest, int id2, int w, int h, int imageSize, int quantum1, int quantum2, bool topIsLow1, bool topIsLow2)
Definition: ImageCopy.cpp:586
An interface for writing to a network connection.
#define IPL_DEPTH_16U
Definition: IplImage.h:108
bool readFromConnection(Image &dest, ImageNetworkHeader &header, ConnectionReader &connection)
This helper function groups code to avoid duplication.
Definition: Image.cpp:44
int GetPadding() const
Definition: Image.cpp:107
unsigned char * getPixelAddress(int x, int y) const
Get address of a pixel in memory.
Definition: Image.h:175
int getRawImageSize() const
Access to the internal buffer size information (this is how much memory has been allocated for the im...
Definition: Image.cpp:734
int nChannels
Most of OpenCV functions support 1,2,3 or 4 channels.
Definition: IplImage.h:132
#define IPL_IMAGE_HEADER
Definition: IplImage.h:346
IplImage * pImage
Definition: Image.cpp:69
static int implemented_yet
Definition: ImageCopy.cpp:45
void resize(int x, int y, int pixel_type, int pixel_size, int quantum, bool topIsLow)
Definition: Image.cpp:137
int width
image width in pixels
Definition: IplImage.h:144
#define yAssert(x)
Definition: Log.h:118
bool isBayer8(int v)
Basic implementations of debayering functions.
Definition: DeBayer.h:19
void setExternal(const void *data, int imgWidth, int imgHeight)
Use this to wrap an external image.
Definition: Image.cpp:1040
void _alloc(void)
Definition: Image.cpp:158
void * getIplImage()
Returns IPL/OpenCV view of image, if possible.
Definition: Image.cpp:743
void initialize()
Definition: Image.cpp:618
An interface for reading from a network connection.
bool topIsLow
Definition: Image.cpp:74
void _set_ipl_header(int x, int y, int pixel_type, int quantum, bool topIsLow)
Definition: Image.cpp:292
int getQuantum() const
The size of a row is constrained to be a multiple of the "quantum".
Definition: Image.h:134
#define IPL_DEPTH_8S
Definition: IplImage.h:111
int depth
pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_...
Definition: IplImage.h:134
void _alloc_extern(const void *buf)
Definition: Image.cpp:175
char colorModel[4]
ignored by OpenCV
Definition: IplImage.h:136
int imageSize
image data size in bytes (==image->height*image->widthStep in case of interleaved data) ...
Definition: IplImage.h:150
#define IPL_DATA_ORDER_PIXEL
Definition: IplImage.h:115
bool isBayer16(int v)
Definition: DeBayer.h:30
#define IPL_BORDER_CONSTANT
Definition: IplImage.h:332
int quantum
Definition: Image.cpp:73
int widthStep
size of aligned image row in bytes
Definition: IplImage.h:154
Image & owner
Definition: Image.cpp:77
void * implementation
Definition: Image.h:325
const char * c_str() const
Accesses the character sequence stored in this object.
Definition: ConstString.cpp:88
void setQuantum(int imgQuantum)
Definition: Image.cpp:702
void _free(void)
Definition: Image.cpp:223
dest h
Definition: ImageCopy.cpp:63
bool deBayer_GRBG8_TO_BGR(yarp::sig::Image &source, yarp::sig::Image &dest, int pixelSize)
Definition: DeBayer.cpp:5
SPECIAL_COPY_BEGIN dest r
Definition: ImageCopy.cpp:50
#define YARP_IMAGE_ALIGN
Definition: IplImage.h:362
virtual bool convertTextMode()=0
Converts a standard description in binary into a textual description, if the connection is in text-mo...
int is_owner
Definition: Image.cpp:81
virtual int getPixelSize() const
Gets pixel size in memory in bytes.
Definition: Image.cpp:639
void _alloc_complete_extern(const void *buf, int x, int y, int pixel_type, int quantum, bool topIsLow)
Definition: Image.cpp:583
bool topIsLow
Definition: Image.h:322
#define IPL_ORIGIN_TL
Definition: IplImage.h:118
virtual bool read(yarp::os::ConnectionReader &connection) YARP_OVERRIDE
Read image from a connection.
Definition: Image.cpp:854
An interface to the operating system, including Port based communication.
int PAD_BYTES(int len, int pad)
computes the padding of YARP images.
Definition: Image.h:31
void setPixelCode(int imgPixelCode)
Definition: Image.cpp:692
void * implementation
Definition: Module.h:218
bool deBayer_GRBG8_TO_RGB(yarp::sig::Image &source, yarp::sig::Image &dest, int pixelSize)
Definition: DeBayer.cpp:71
const Image & operator=(const Image &alt)
Assignment operator.
Definition: Image.cpp:1000
Signal processing.
Definition: Image.h:20
virtual bool write(yarp::os::ConnectionWriter &connection) YARP_OVERRIDE
Write image to a connection.
Definition: Image.cpp:955
int _pad_bytes(int linesize, int align) const
Definition: Image.cpp:602
virtual bool expectBlock(const char *data, size_t len)=0
Read a block of data from the network connection.
int height() const
Gets height of image in pixels.
Definition: Image.h:107
void setQuantum(int imgQuantum)
Definition: Image.h:352
void _alloc_complete(int x, int y, int pixel_type, int quantum, bool topIsLow)
Definition: Image.cpp:274
memcpy(dstImage->imageData, srcImage->imageData, srcImage->imageSize)
virtual bool isError()=0
virtual int getPixelCode() const
Gets pixel type identifier.
Definition: Image.cpp:644