Visual Servoing Platform  version 3.2.0 under development (2019-01-22)
vpImageConvert.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Convert image types.
33  *
34  * Authors:
35  * Eric Marchand
36  * Fabien Spindler
37  * Anthony Saunier
38  *
39  *****************************************************************************/
40 
46 #include <map>
47 #include <sstream>
48 
49 // image
50 #include <visp3/core/vpCPUFeatures.h>
51 #include <visp3/core/vpImageConvert.h>
52 
53 #if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2)
54 #include <emmintrin.h>
55 #define VISP_HAVE_SSE2 1
56 
57 #if defined __SSE3__ || (defined _MSC_VER && _MSC_VER >= 1500)
58 #include <pmmintrin.h>
59 #define VISP_HAVE_SSE3 1
60 #endif
61 #if defined __SSSE3__ || (defined _MSC_VER && _MSC_VER >= 1500)
62 #include <tmmintrin.h>
63 #define VISP_HAVE_SSSE3 1
64 #endif
65 #endif
66 
67 bool vpImageConvert::YCbCrLUTcomputed = false;
68 int vpImageConvert::vpCrr[256];
69 int vpImageConvert::vpCgb[256];
70 int vpImageConvert::vpCgr[256];
71 int vpImageConvert::vpCbb[256];
72 
80 {
81  dest.resize(src.getHeight(), src.getWidth());
82 
83  GreyToRGBa(src.bitmap, (unsigned char *)dest.bitmap, src.getHeight() * src.getWidth());
84 }
85 
92 {
93  dest.resize(src.getHeight(), src.getWidth());
94 
95  RGBaToGrey((unsigned char *)src.bitmap, dest.bitmap, src.getHeight() * src.getWidth());
96 }
97 
103 {
104  dest.resize(src.getHeight(), src.getWidth());
105  unsigned int max_xy = src.getWidth() * src.getHeight();
106  float min, max;
107 
108  src.getMinMaxValue(min, max);
109 
110  for (unsigned int i = 0; i < max_xy; i++) {
111  float val = 255.f * (src.bitmap[i] - min) / (max - min);
112  if (val < 0)
113  dest.bitmap[i] = 0;
114  else if (val > 255)
115  dest.bitmap[i] = 255;
116  else
117  dest.bitmap[i] = (unsigned char)val;
118  }
119 }
120 
127 {
128  dest.resize(src.getHeight(), src.getWidth());
129  for (unsigned int i = 0; i < src.getHeight() * src.getWidth(); i++)
130  dest.bitmap[i] = (float)src.bitmap[i];
131 }
132 
138 {
139  dest.resize(src.getHeight(), src.getWidth());
140  unsigned int max_xy = src.getWidth() * src.getHeight();
141  double min, max;
142 
143  src.getMinMaxValue(min, max);
144 
145  for (unsigned int i = 0; i < max_xy; i++) {
146  double val = 255. * (src.bitmap[i] - min) / (max - min);
147  if (val < 0)
148  dest.bitmap[i] = 0;
149  else if (val > 255)
150  dest.bitmap[i] = 255;
151  else
152  dest.bitmap[i] = (unsigned char)val;
153  }
154 }
155 
162 {
163  dest.resize(src.getHeight(), src.getWidth());
164 
165  for (unsigned int i = 0; i < src.getSize(); i++)
166  dest.bitmap[i] = (src.bitmap[i] >> 8);
167 }
168 
175 {
176  dest.resize(src.getHeight(), src.getWidth());
177 
178  for (unsigned int i = 0; i < src.getSize(); i++)
179  dest.bitmap[i] = (src.bitmap[i] << 8);
180 }
181 
188 {
189  dest.resize(src.getHeight(), src.getWidth());
190  for (unsigned int i = 0; i < src.getHeight() * src.getWidth(); i++)
191  dest.bitmap[i] = (double)src.bitmap[i];
192 }
193 
202 {
203  dest_rgba.resize(src_depth.getHeight(), src_depth.getWidth());
204  static uint32_t histogram[0x10000];
205  memset(histogram, 0, sizeof(histogram));
206 
207  for (unsigned int i = 0; i < src_depth.getSize(); ++i)
208  ++histogram[src_depth.bitmap[i]];
209  for (int i = 2; i < 0x10000; ++i)
210  histogram[i] += histogram[i - 1]; // Build a cumulative histogram for the
211  // indices in [1,0xFFFF]
212 
213  for (unsigned int i = 0; i < src_depth.getSize(); ++i) {
214  uint16_t d = src_depth.bitmap[i];
215  if (d) {
216  int f = (int)(histogram[d] * 255 / histogram[0xFFFF]); // 0-255 based on histogram location
217  dest_rgba.bitmap[i].R = 255 - f;
218  dest_rgba.bitmap[i].G = 0;
219  dest_rgba.bitmap[i].B = f;
220  dest_rgba.bitmap[i].A = vpRGBa::alpha_default;
221  } else {
222  dest_rgba.bitmap[i].R = 20;
223  dest_rgba.bitmap[i].G = 5;
224  dest_rgba.bitmap[i].B = 0;
225  dest_rgba.bitmap[i].A = vpRGBa::alpha_default;
226  }
227  }
228 }
229 
237 {
238  dest_depth.resize(src_depth.getHeight(), src_depth.getWidth());
239  static uint32_t histogram2[0x10000];
240  memset(histogram2, 0, sizeof(histogram2));
241 
242  for (unsigned int i = 0; i < src_depth.getSize(); ++i)
243  ++histogram2[src_depth.bitmap[i]];
244  for (int i = 2; i < 0x10000; ++i)
245  histogram2[i] += histogram2[i - 1]; // Build a cumulative histogram for
246  // the indices in [1,0xFFFF]
247 
248  for (unsigned int i = 0; i < src_depth.getSize(); ++i) {
249  uint16_t d = src_depth.bitmap[i];
250  if (d) {
251  int f = (int)(histogram2[d] * 255 / histogram2[0xFFFF]); // 0-255 based on histogram location
252  dest_depth.bitmap[i] = f;
253  } else {
254  dest_depth.bitmap[i] = 0;
255  }
256  }
257 }
258 
259 #ifdef VISP_HAVE_OPENCV
260 // Deprecated: will be removed with OpenCV transcient from C to C++ api
307 void vpImageConvert::convert(const IplImage *src, vpImage<vpRGBa> &dest, bool flip)
308 {
309  int nChannel = src->nChannels;
310  int depth = src->depth;
311  int height = src->height;
312  int width = src->width;
313  int widthStep = src->widthStep;
314  int lineStep = (flip) ? 1 : 0;
315 
316  if (nChannel == 3 && depth == 8) {
317  dest.resize((unsigned int)height, (unsigned int)width);
318 
319  // starting source address
320  unsigned char *input = (unsigned char *)src->imageData;
321  unsigned char *beginOutput = (unsigned char *)dest.bitmap;
322 
323  for (int i = 0; i < height; i++) {
324  unsigned char *line = input;
325  unsigned char *output = beginOutput + lineStep * (4 * width * (height - 1 - i)) + (1 - lineStep) * 4 * width * i;
326  for (int j = 0; j < width; j++) {
327  *(output++) = *(line + 2);
328  *(output++) = *(line + 1);
329  *(output++) = *(line);
330  *(output++) = vpRGBa::alpha_default;
331 
332  line += 3;
333  }
334  // go to the next line
335  input += widthStep;
336  }
337  } else if (nChannel == 1 && depth == 8) {
338  dest.resize((unsigned int)height, (unsigned int)width);
339  // starting source address
340  unsigned char *input = (unsigned char *)src->imageData;
341  unsigned char *beginOutput = (unsigned char *)dest.bitmap;
342 
343  for (int i = 0; i < height; i++) {
344  unsigned char *line = input;
345  unsigned char *output = beginOutput + lineStep * (4 * width * (height - 1 - i)) + (1 - lineStep) * 4 * width * i;
346  for (int j = 0; j < width; j++) {
347  *output++ = *(line);
348  *output++ = *(line);
349  *output++ = *(line);
350  *output++ = vpRGBa::alpha_default; // alpha
351 
352  line++;
353  }
354  // go to the next line
355  input += widthStep;
356  }
357  }
358 }
359 
403 void vpImageConvert::convert(const IplImage *src, vpImage<unsigned char> &dest, bool flip)
404 {
405  int nChannel = src->nChannels;
406  int depth = src->depth;
407  int height = src->height;
408  int width = src->width;
409  int widthStep = src->widthStep;
410  int lineStep = (flip) ? 1 : 0;
411 
412  if (flip == false) {
413  if (widthStep == width) {
414  if (nChannel == 1 && depth == 8) {
415  dest.resize((unsigned int)height, (unsigned int)width);
416  memcpy(dest.bitmap, src->imageData, (size_t)(height * width));
417  }
418  if (nChannel == 3 && depth == 8) {
419  dest.resize((unsigned int)height, (unsigned int)width);
420  BGRToGrey((unsigned char *)src->imageData, dest.bitmap, (unsigned int)width, (unsigned int)height, false);
421  }
422  } else {
423  if (nChannel == 1 && depth == 8) {
424  dest.resize((unsigned int)height, (unsigned int)width);
425  for (int i = 0; i < height; i++) {
426  memcpy(dest.bitmap + i * width, src->imageData + i * widthStep, (size_t)width);
427  }
428  }
429  if (nChannel == 3 && depth == 8) {
430  dest.resize((unsigned int)height, (unsigned int)width);
431  for (int i = 0; i < height; i++) {
432  BGRToGrey((unsigned char *)src->imageData + i * widthStep, dest.bitmap + i * width, (unsigned int)width, 1,
433  false);
434  }
435  }
436  }
437  } else {
438  if (nChannel == 1 && depth == 8) {
439  dest.resize((unsigned int)height, (unsigned int)width);
440  unsigned char *beginOutput = (unsigned char *)dest.bitmap;
441  for (int i = 0; i < height; i++) {
442  memcpy(beginOutput + lineStep * (4 * width * (height - 1 - i)), src->imageData + i * widthStep, (size_t)width);
443  }
444  }
445  if (nChannel == 3 && depth == 8) {
446  dest.resize((unsigned int)height, (unsigned int)width);
447  // for (int i = 0 ; i < height ; i++){
448  BGRToGrey((unsigned char *)src->imageData /*+ i*widthStep*/, dest.bitmap /*+ i*width*/, (unsigned int)width,
449  (unsigned int)height /*1*/, true);
450  //}
451  }
452  }
453 }
454 
499 void vpImageConvert::convert(const vpImage<vpRGBa> &src, IplImage *&dest)
500 {
501  int height = (int)src.getHeight();
502  int width = (int)src.getWidth();
503  CvSize size = cvSize(width, height);
504  int depth = 8;
505  int channels = 3;
506  if (dest != NULL) {
507  if (dest->nChannels != channels || dest->depth != depth || dest->height != height || dest->width != width) {
508  if (dest->nChannels != 0)
509  cvReleaseImage(&dest);
510  dest = cvCreateImage(size, depth, channels);
511  }
512  } else
513  dest = cvCreateImage(size, depth, channels);
514 
515  // starting source address
516  unsigned char *input = (unsigned char *)src.bitmap; // rgba image
517  unsigned char *output = (unsigned char *)dest->imageData; // bgr image
518 
519  int j = 0;
520  int i = 0;
521  int widthStep = dest->widthStep;
522 
523  for (i = 0; i < height; i++) {
524  output = (unsigned char *)dest->imageData + i * widthStep;
525  unsigned char *line = input;
526  for (j = 0; j < width; j++) {
527  *output++ = *(line + 2); // B
528  *output++ = *(line + 1); // G
529  *output++ = *(line); // R
530 
531  line += 4;
532  }
533  // go to the next line
534  input += 4 * width;
535  }
536 }
537 
582 void vpImageConvert::convert(const vpImage<unsigned char> &src, IplImage *&dest)
583 {
584  unsigned int height = src.getHeight();
585  unsigned int width = src.getWidth();
586  CvSize size = cvSize((int)width, (int)height);
587  int depth = 8;
588  int channels = 1;
589  if (dest != NULL) {
590  if (dest->nChannels != channels || dest->depth != depth || dest->height != (int)height ||
591  dest->width != (int)width) {
592  if (dest->nChannels != 0)
593  cvReleaseImage(&dest);
594  dest = cvCreateImage(size, depth, channels);
595  }
596  } else
597  dest = cvCreateImage(size, depth, channels);
598 
599  unsigned int widthStep = (unsigned int)dest->widthStep;
600 
601  if (width == widthStep) {
602  memcpy(dest->imageData, src.bitmap, width * height);
603  } else {
604  // copying each line taking account of the widthStep
605  for (unsigned int i = 0; i < height; i++) {
606  memcpy(dest->imageData + i * widthStep, src.bitmap + i * width, width);
607  }
608  }
609 }
610 
611 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
612 
660 void vpImageConvert::convert(const cv::Mat &src, vpImage<vpRGBa> &dest, const bool flip)
661 {
662  if (src.type() == CV_8UC4) {
663  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
664  vpRGBa rgbaVal;
665  for (unsigned int i = 0; i < dest.getRows(); ++i)
666  for (unsigned int j = 0; j < dest.getCols(); ++j) {
667  cv::Vec4b tmp = src.at<cv::Vec4b>((int)i, (int)j);
668  rgbaVal.R = tmp[2];
669  rgbaVal.G = tmp[1];
670  rgbaVal.B = tmp[0];
671  rgbaVal.A = tmp[3];
672  if (flip)
673  dest[dest.getRows() - i - 1][j] = rgbaVal;
674  else
675  dest[i][j] = rgbaVal;
676  }
677  } else if (src.type() == CV_8UC3) {
678  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
679 
680  bool checkSSSE3 = vpCPUFeatures::checkSSSE3();
681  #if !VISP_HAVE_SSSE3
682  checkSSSE3 = false;
683  #endif
684 
685  if (checkSSSE3 && src.isContinuous() && !flip) {
686 #if VISP_HAVE_SSSE3
687  int i = 0;
688  int size = src.rows*src.cols;
689  const uchar* bgr = src.ptr<uchar>();
690  unsigned char* rgba = (unsigned char*) dest.bitmap;
691 
692  if (size >= 16) {
693  // Mask to reorder BGR to RGBa
694  const __m128i mask_1 = _mm_set_epi8(-1, 9, 10, 11, -1, 6, 7, 8, -1, 3, 4, 5, -1, 0, 1, 2);
695  const __m128i mask_2 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, 12, 13, 14);
696  const __m128i mask_3 = _mm_set_epi8(-1, 5, 6, 7, -1, 2, 3, 4, -1, -1, 0, 1, -1, -1, -1, -1);
697  const __m128i mask_4 = _mm_set_epi8(-1, -1, -1, -1, -1, 14, 15, -1, -1, 11, 12, 13, -1, 8, 9, 10);
698  const __m128i mask_5 = _mm_set_epi8(-1, 1, 2, 3, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1);
699  const __m128i mask_6 = _mm_set_epi8(-1, 13, 14, 15, -1, 10, 11, 12, -1, 7, 8, 9, -1, 4, 5, 6);
700 
701  __m128i res[4];
702  int size_vec = size - 16;
703  // Note: size_vec introduced to avoid warning: assuming signed overflow does not occur
704  // when simplifying range test [-Wstrict-overflow]
705  for (; i <= size_vec; i += 16) {
706  // Process 16 BGR color pixels
707  const __m128i data1 = _mm_loadu_si128((const __m128i *)bgr);
708  const __m128i data2 = _mm_loadu_si128((const __m128i *)(bgr + 16));
709  const __m128i data3 = _mm_loadu_si128((const __m128i *)(bgr + 32));
710 
711  res[0] = _mm_shuffle_epi8(data1, mask_1);
712  res[1] = _mm_or_si128(_mm_shuffle_epi8(data1, mask_2), _mm_shuffle_epi8(data2, mask_3));
713  res[2] = _mm_or_si128(_mm_shuffle_epi8(data2, mask_4), _mm_shuffle_epi8(data3, mask_5));
714  res[3] = _mm_shuffle_epi8(data3, mask_6);
715 
716  _mm_storeu_si128((__m128i *)rgba, res[0]);
717  _mm_storeu_si128((__m128i *)(rgba+16), res[1]);
718  _mm_storeu_si128((__m128i *)(rgba+32), res[2]);
719  _mm_storeu_si128((__m128i *)(rgba+48), res[3]);
720 
721  bgr += 48;
722  rgba += 64;
723  }
724  }
725 
726  for (; i < size; i++) {
727  *rgba = *(bgr+2); rgba++;
728  *rgba = *(bgr+1); rgba++;
729  *rgba = *(bgr); rgba++;
730  *rgba = 0; rgba++;
731 
732  bgr += 3;
733  }
734 #endif
735  } else {
736  vpRGBa rgbaVal;
737  rgbaVal.A = vpRGBa::alpha_default;
738  for (unsigned int i = 0; i < dest.getRows(); ++i) {
739  for (unsigned int j = 0; j < dest.getCols(); ++j) {
740  cv::Vec3b tmp = src.at<cv::Vec3b>((int)i, (int)j);
741  rgbaVal.R = tmp[2];
742  rgbaVal.G = tmp[1];
743  rgbaVal.B = tmp[0];
744  if (flip) {
745  dest[dest.getRows() - i - 1][j] = rgbaVal;
746  } else {
747  dest[i][j] = rgbaVal;
748  }
749  }
750  }
751  }
752  } else if (src.type() == CV_8UC1) {
753  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
754  vpRGBa rgbaVal;
755  for (unsigned int i = 0; i < dest.getRows(); ++i) {
756  for (unsigned int j = 0; j < dest.getCols(); ++j) {
757  rgbaVal = src.at<unsigned char>((int)i, (int)j);
758  if (flip) {
759  dest[dest.getRows() - i - 1][j] = rgbaVal;
760  } else {
761  dest[i][j] = rgbaVal;
762  }
763  }
764  }
765  }
766 }
767 
810 void vpImageConvert::convert(const cv::Mat &src, vpImage<unsigned char> &dest, const bool flip)
811 {
812  if (src.type() == CV_8UC1) {
813  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
814  if (src.isContinuous() && !flip) {
815  memcpy(dest.bitmap, src.data, (size_t)(src.rows * src.cols));
816  } else {
817  if (flip) {
818  for (unsigned int i = 0; i < dest.getRows(); ++i) {
819  memcpy(dest.bitmap + i * dest.getCols(), src.data + (dest.getRows() - i - 1) * src.step1(), (size_t)src.step);
820  }
821  } else {
822  for (unsigned int i = 0; i < dest.getRows(); ++i) {
823  memcpy(dest.bitmap + i * dest.getCols(), src.data + i * src.step1(), (size_t)src.step);
824  }
825  }
826  }
827  } else if (src.type() == CV_8UC3) {
828  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
829  if (src.isContinuous() /*&& !flip*/) {
830  BGRToGrey((unsigned char *)src.data, (unsigned char *)dest.bitmap, (unsigned int)src.cols, (unsigned int)src.rows,
831  flip);
832  } else {
833  if (flip) {
834  for (unsigned int i = 0; i < dest.getRows(); ++i) {
835  BGRToGrey((unsigned char *)src.data + i * src.step1(),
836  (unsigned char *)dest.bitmap + (dest.getRows() - i - 1) * dest.getCols(),
837  (unsigned int)dest.getCols(), 1, false);
838  }
839  } else {
840  for (unsigned int i = 0; i < dest.getRows(); ++i) {
841  BGRToGrey((unsigned char *)src.data + i * src.step1(), (unsigned char *)dest.bitmap + i * dest.getCols(),
842  (unsigned int)dest.getCols(), 1, false);
843  }
844  }
845  }
846  }
847 }
848 
888 void vpImageConvert::convert(const vpImage<vpRGBa> &src, cv::Mat &dest)
889 {
890  cv::Mat vpToMat((int)src.getRows(), (int)src.getCols(), CV_8UC4, (void *)src.bitmap);
891  cv::cvtColor(vpToMat, dest, cv::COLOR_RGBA2BGR);
892 }
893 
935 void vpImageConvert::convert(const vpImage<unsigned char> &src, cv::Mat &dest, const bool copyData)
936 {
937  if (copyData) {
938  cv::Mat tmpMap((int)src.getRows(), (int)src.getCols(), CV_8UC1, (void *)src.bitmap);
939  dest = tmpMap.clone();
940  } else {
941  dest = cv::Mat((int)src.getRows(), (int)src.getCols(), CV_8UC1, (void *)src.bitmap);
942  }
943 }
944 
945 #endif
946 #endif
947 
948 #ifdef VISP_HAVE_YARP
949 
984 void vpImageConvert::convert(const vpImage<unsigned char> &src, yarp::sig::ImageOf<yarp::sig::PixelMono> *dest,
985  const bool copyData)
986 {
987  if (copyData) {
988  dest->resize(src.getWidth(), src.getHeight());
989  memcpy(dest->getRawImage(), src.bitmap, src.getHeight() * src.getWidth());
990  } else
991  dest->setExternal(src.bitmap, (int)src.getCols(), (int)src.getRows());
992 }
993 
1033 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelMono> *src, vpImage<unsigned char> &dest,
1034  const bool copyData)
1035 {
1036  dest.resize(src->height(), src->width());
1037  if (copyData)
1038  memcpy(dest.bitmap, src->getRawImage(), src->height() * src->width() * sizeof(yarp::sig::PixelMono));
1039  else
1040  dest.bitmap = src->getRawImage();
1041 }
1042 
1078 void vpImageConvert::convert(const vpImage<vpRGBa> &src, yarp::sig::ImageOf<yarp::sig::PixelRgba> *dest,
1079  const bool copyData)
1080 {
1081  if (copyData) {
1082  dest->resize(src.getWidth(), src.getHeight());
1083  memcpy(dest->getRawImage(), src.bitmap, src.getHeight() * src.getWidth() * sizeof(vpRGBa));
1084  } else
1085  dest->setExternal(src.bitmap, (int)src.getCols(), (int)src.getRows());
1086 }
1087 
1127 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelRgba> *src, vpImage<vpRGBa> &dest,
1128  const bool copyData)
1129 {
1130  dest.resize(src->height(), src->width());
1131  if (copyData)
1132  memcpy(dest.bitmap, src->getRawImage(), src->height() * src->width() * sizeof(yarp::sig::PixelRgba));
1133  else
1134  dest.bitmap = static_cast<vpRGBa *>(src->getRawImage());
1135 }
1136 
1170 void vpImageConvert::convert(const vpImage<vpRGBa> &src, yarp::sig::ImageOf<yarp::sig::PixelRgb> *dest)
1171 {
1172  dest->resize(src.getWidth(), src.getHeight());
1173  for (unsigned int i = 0; i < src.getRows(); i++) {
1174  for (unsigned int j = 0; j < src.getWidth(); j++) {
1175  dest->pixel(j, i).r = src[i][j].R;
1176  dest->pixel(j, i).g = src[i][j].G;
1177  dest->pixel(j, i).b = src[i][j].B;
1178  }
1179  }
1180 }
1181 
1221 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelRgb> *src, vpImage<vpRGBa> &dest)
1222 {
1223  dest.resize(src->height(), src->width());
1224  for (int i = 0; i < src->height(); i++) {
1225  for (int j = 0; j < src->width(); j++) {
1226  dest[i][j].R = src->pixel(j, i).r;
1227  dest[i][j].G = src->pixel(j, i).g;
1228  dest[i][j].B = src->pixel(j, i).b;
1229  dest[i][j].A = vpRGBa::alpha_default;
1230  }
1231  }
1232 }
1233 
1234 #endif
1235 
1236 #define vpSAT(c) \
1237  if (c & (~255)) { \
1238  if (c < 0) \
1239  c = 0; \
1240  else \
1241  c = 255; \
1242  }
1243 
1251 void vpImageConvert::YUYVToRGBa(unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height)
1252 {
1253  unsigned char *s;
1254  unsigned char *d;
1255  int w, h;
1256  int r, g, b, cr, cg, cb, y1, y2;
1257 
1258  h = (int)height;
1259  w = (int)width;
1260  s = yuyv;
1261  d = rgba;
1262  while (h--) {
1263  int c = w >> 1;
1264  while (c--) {
1265  y1 = *s++;
1266  cb = ((*s - 128) * 454) >> 8;
1267  cg = (*s++ - 128) * 88;
1268  y2 = *s++;
1269  cr = ((*s - 128) * 359) >> 8;
1270  cg = (cg + (*s++ - 128) * 183) >> 8;
1271 
1272  r = y1 + cr;
1273  b = y1 + cb;
1274  g = y1 - cg;
1275  vpSAT(r);
1276  vpSAT(g);
1277  vpSAT(b);
1278 
1279  *d++ = static_cast<unsigned char>(r);
1280  *d++ = static_cast<unsigned char>(g);
1281  *d++ = static_cast<unsigned char>(b);
1282  *d++ = vpRGBa::alpha_default;
1283 
1284  r = y2 + cr;
1285  b = y2 + cb;
1286  g = y2 - cg;
1287  vpSAT(r);
1288  vpSAT(g);
1289  vpSAT(b);
1290 
1291  *d++ = static_cast<unsigned char>(r);
1292  *d++ = static_cast<unsigned char>(g);
1293  *d++ = static_cast<unsigned char>(b);
1294  *d++ = vpRGBa::alpha_default;
1295  }
1296  }
1297 }
1298 
1306 void vpImageConvert::YUYVToRGB(unsigned char *yuyv, unsigned char *rgb, unsigned int width, unsigned int height)
1307 {
1308  unsigned char *s;
1309  unsigned char *d;
1310  int h, w;
1311  int r, g, b, cr, cg, cb, y1, y2;
1312 
1313  h = (int)height;
1314  w = (int)width;
1315  s = yuyv;
1316  d = rgb;
1317  while (h--) {
1318  int c = w >> 1;
1319  while (c--) {
1320  y1 = *s++;
1321  cb = ((*s - 128) * 454) >> 8;
1322  cg = (*s++ - 128) * 88;
1323  y2 = *s++;
1324  cr = ((*s - 128) * 359) >> 8;
1325  cg = (cg + (*s++ - 128) * 183) >> 8;
1326 
1327  r = y1 + cr;
1328  b = y1 + cb;
1329  g = y1 - cg;
1330  vpSAT(r);
1331  vpSAT(g);
1332  vpSAT(b);
1333 
1334  *d++ = static_cast<unsigned char>(r);
1335  *d++ = static_cast<unsigned char>(g);
1336  *d++ = static_cast<unsigned char>(b);
1337 
1338  r = y2 + cr;
1339  b = y2 + cb;
1340  g = y2 - cg;
1341  vpSAT(r);
1342  vpSAT(g);
1343  vpSAT(b);
1344 
1345  *d++ = static_cast<unsigned char>(r);
1346  *d++ = static_cast<unsigned char>(g);
1347  *d++ = static_cast<unsigned char>(b);
1348  }
1349  }
1350 }
1358 void vpImageConvert::YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
1359 {
1360  unsigned int i = 0, j = 0;
1361 
1362  while (j < size * 2) {
1363  grey[i++] = yuyv[j];
1364  grey[i++] = yuyv[j + 2];
1365  j += 4;
1366  }
1367 }
1368 
1375 void vpImageConvert::YUV411ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
1376 {
1377 #if 1
1378  // std::cout << "call optimized ConvertYUV411ToRGBa()" << std::endl;
1379  for (unsigned int i = size / 4; i; i--) {
1380  int U = (int)((*yuv++ - 128) * 0.354);
1381  int U5 = 5 * U;
1382  int Y0 = *yuv++;
1383  int Y1 = *yuv++;
1384  int V = (int)((*yuv++ - 128) * 0.707);
1385  int V2 = 2 * V;
1386  int Y2 = *yuv++;
1387  int Y3 = *yuv++;
1388  int UV = -U - V;
1389 
1390  // Original equations
1391  // R = Y + 1.402 V
1392  // G = Y - 0.344 U - 0.714 V
1393  // B = Y + 1.772 U
1394  int R = Y0 + V2;
1395  if ((R >> 8) > 0)
1396  R = 255;
1397  else if (R < 0)
1398  R = 0;
1399 
1400  int G = Y0 + UV;
1401  if ((G >> 8) > 0)
1402  G = 255;
1403  else if (G < 0)
1404  G = 0;
1405 
1406  int B = Y0 + U5;
1407  if ((B >> 8) > 0)
1408  B = 255;
1409  else if (B < 0)
1410  B = 0;
1411 
1412  *rgba++ = (unsigned char)R;
1413  *rgba++ = (unsigned char)G;
1414  *rgba++ = (unsigned char)B;
1415  *rgba++ = vpRGBa::alpha_default;
1416 
1417  //---
1418  R = Y1 + V2;
1419  if ((R >> 8) > 0)
1420  R = 255;
1421  else if (R < 0)
1422  R = 0;
1423 
1424  G = Y1 + UV;
1425  if ((G >> 8) > 0)
1426  G = 255;
1427  else if (G < 0)
1428  G = 0;
1429 
1430  B = Y1 + U5;
1431  if ((B >> 8) > 0)
1432  B = 255;
1433  else if (B < 0)
1434  B = 0;
1435 
1436  *rgba++ = (unsigned char)R;
1437  *rgba++ = (unsigned char)G;
1438  *rgba++ = (unsigned char)B;
1439  *rgba++ = vpRGBa::alpha_default;
1440 
1441  //---
1442  R = Y2 + V2;
1443  if ((R >> 8) > 0)
1444  R = 255;
1445  else if (R < 0)
1446  R = 0;
1447 
1448  G = Y2 + UV;
1449  if ((G >> 8) > 0)
1450  G = 255;
1451  else if (G < 0)
1452  G = 0;
1453 
1454  B = Y2 + U5;
1455  if ((B >> 8) > 0)
1456  B = 255;
1457  else if (B < 0)
1458  B = 0;
1459 
1460  *rgba++ = (unsigned char)R;
1461  *rgba++ = (unsigned char)G;
1462  *rgba++ = (unsigned char)B;
1463  *rgba++ = vpRGBa::alpha_default;
1464 
1465  //---
1466  R = Y3 + V2;
1467  if ((R >> 8) > 0)
1468  R = 255;
1469  else if (R < 0)
1470  R = 0;
1471 
1472  G = Y3 + UV;
1473  if ((G >> 8) > 0)
1474  G = 255;
1475  else if (G < 0)
1476  G = 0;
1477 
1478  B = Y3 + U5;
1479  if ((B >> 8) > 0)
1480  B = 255;
1481  else if (B < 0)
1482  B = 0;
1483 
1484  *rgba++ = (unsigned char)R;
1485  *rgba++ = (unsigned char)G;
1486  *rgba++ = (unsigned char)B;
1487  *rgba++ = vpRGBa::alpha_default;
1488  }
1489 #else
1490  // tres tres lent ....
1491  unsigned int i = 0, j = 0;
1492  unsigned char r, g, b;
1493  while (j < numpixels * 3 / 2) {
1494 
1495  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 3], r, g, b);
1496  rgba[i] = r;
1497  rgba[i + 1] = g;
1498  rgba[i + 2] = b;
1499  rgba[i + 3] = vpRGBa::alpha_default;
1500  i += 4;
1501 
1502  YUVToRGB(yuv[j + 2], yuv[j], yuv[j + 3], r, g, b);
1503  rgba[i] = r;
1504  rgba[i + 1] = g;
1505  rgba[i + 2] = b;
1506  rgba[i + 3] = vpRGBa::alpha_default;
1507  i += 4;
1508 
1509  YUVToRGB(yuv[j + 4], yuv[j], yuv[j + 3], r, g, b);
1510  rgba[i] = r;
1511  rgba[i + 1] = g;
1512  rgba[i + 2] = b;
1513  rgba[i + 3] = vpRGBa::alpha_default;
1514  i += 4;
1515 
1516  YUVToRGB(yuv[j + 5], yuv[j], yuv[j + 3], r, g, b);
1517  rgba[i] = r;
1518  rgba[i + 1] = g;
1519  rgba[i + 2] = b;
1520  rgba[i + 3] = vpRGBa::alpha_default;
1521  i += 4;
1522 
1523  j += 6;
1524  }
1525 #endif
1526 }
1527 
1536 void vpImageConvert::YUV422ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
1537 {
1538 
1539 #if 1
1540  // std::cout << "call optimized convertYUV422ToRGBa()" << std::endl;
1541  for (unsigned int i = size / 2; i; i--) {
1542  int U = (int)((*yuv++ - 128) * 0.354);
1543  int U5 = 5 * U;
1544  int Y0 = *yuv++;
1545  int V = (int)((*yuv++ - 128) * 0.707);
1546  int V2 = 2 * V;
1547  int Y1 = *yuv++;
1548  int UV = -U - V;
1549 
1550  //---
1551  int R = Y0 + V2;
1552  if ((R >> 8) > 0)
1553  R = 255;
1554  else if (R < 0)
1555  R = 0;
1556 
1557  int G = Y0 + UV;
1558  if ((G >> 8) > 0)
1559  G = 255;
1560  else if (G < 0)
1561  G = 0;
1562 
1563  int B = Y0 + U5;
1564  if ((B >> 8) > 0)
1565  B = 255;
1566  else if (B < 0)
1567  B = 0;
1568 
1569  *rgba++ = (unsigned char)R;
1570  *rgba++ = (unsigned char)G;
1571  *rgba++ = (unsigned char)B;
1572  *rgba++ = vpRGBa::alpha_default;
1573 
1574  //---
1575  R = Y1 + V2;
1576  if ((R >> 8) > 0)
1577  R = 255;
1578  else if (R < 0)
1579  R = 0;
1580 
1581  G = Y1 + UV;
1582  if ((G >> 8) > 0)
1583  G = 255;
1584  else if (G < 0)
1585  G = 0;
1586 
1587  B = Y1 + U5;
1588  if ((B >> 8) > 0)
1589  B = 255;
1590  else if (B < 0)
1591  B = 0;
1592 
1593  *rgba++ = (unsigned char)R;
1594  *rgba++ = (unsigned char)G;
1595  *rgba++ = (unsigned char)B;
1596  *rgba++ = vpRGBa::alpha_default;
1597  }
1598 
1599 #else
1600  // tres tres lent ....
1601  unsigned int i = 0, j = 0;
1602  unsigned char r, g, b;
1603 
1604  while (j < size * 2) {
1605 
1606  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 2], r, g, b);
1607  rgba[i] = r;
1608  rgba[i + 1] = g;
1609  rgba[i + 2] = b;
1610  rgba[i + 3] = vpRGBa::alpha_default;
1611  i += 4;
1612 
1613  YUVToRGB(yuv[j + 3], yuv[j], yuv[j + 2], r, g, b);
1614  rgba[i] = r;
1615  rgba[i + 1] = g;
1616  rgba[i + 2] = b;
1617  rgba[i + 3] = vpRGBa::alpha_default;
1618  i += 4;
1619  j += 4;
1620  }
1621 #endif
1622 }
1623 
1630 void vpImageConvert::YUV411ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
1631 {
1632  unsigned int i = 0, j = 0;
1633  while (j < size * 3 / 2) {
1634  grey[i] = yuv[j + 1];
1635  grey[i + 1] = yuv[j + 2];
1636  grey[i + 2] = yuv[j + 4];
1637  grey[i + 3] = yuv[j + 5];
1638 
1639  i += 4;
1640 
1641  j += 6;
1642  }
1643 }
1644 
1653 void vpImageConvert::YUV422ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
1654 {
1655 #if 1
1656  // std::cout << "call optimized convertYUV422ToRGB()" << std::endl;
1657  for (unsigned int i = size / 2; i; i--) {
1658  int U = (int)((*yuv++ - 128) * 0.354);
1659  int U5 = 5 * U;
1660  int Y0 = *yuv++;
1661  int V = (int)((*yuv++ - 128) * 0.707);
1662  int V2 = 2 * V;
1663  int Y1 = *yuv++;
1664  int UV = -U - V;
1665 
1666  //---
1667  int R = Y0 + V2;
1668  if ((R >> 8) > 0)
1669  R = 255;
1670  else if (R < 0)
1671  R = 0;
1672 
1673  int G = Y0 + UV;
1674  if ((G >> 8) > 0)
1675  G = 255;
1676  else if (G < 0)
1677  G = 0;
1678 
1679  int B = Y0 + U5;
1680  if ((B >> 8) > 0)
1681  B = 255;
1682  else if (B < 0)
1683  B = 0;
1684 
1685  *rgb++ = (unsigned char)R;
1686  *rgb++ = (unsigned char)G;
1687  *rgb++ = (unsigned char)B;
1688 
1689  //---
1690  R = Y1 + V2;
1691  if ((R >> 8) > 0)
1692  R = 255;
1693  else if (R < 0)
1694  R = 0;
1695 
1696  G = Y1 + UV;
1697  if ((G >> 8) > 0)
1698  G = 255;
1699  else if (G < 0)
1700  G = 0;
1701 
1702  B = Y1 + U5;
1703  if ((B >> 8) > 0)
1704  B = 255;
1705  else if (B < 0)
1706  B = 0;
1707 
1708  *rgb++ = (unsigned char)R;
1709  *rgb++ = (unsigned char)G;
1710  *rgb++ = (unsigned char)B;
1711  }
1712 
1713 #else
1714  // tres tres lent ....
1715  unsigned int i = 0, j = 0;
1716  unsigned char r, g, b;
1717 
1718  while (j < size * 2) {
1719 
1720  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 2], r, g, b);
1721  rgb[i] = r;
1722  rgb[i + 1] = g;
1723  rgb[i + 2] = b;
1724  i += 3;
1725 
1726  YUVToRGB(yuv[j + 3], yuv[j], yuv[j + 2], r, g, b);
1727  rgb[i] = r;
1728  rgb[i + 1] = g;
1729  rgb[i + 2] = b;
1730  i += 3;
1731  j += 4;
1732  }
1733 #endif
1734 }
1735 
1744 void vpImageConvert::YUV422ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
1745 {
1746  unsigned int i = 0, j = 0;
1747 
1748  while (j < size * 2) {
1749  grey[i++] = yuv[j + 1];
1750  grey[i++] = yuv[j + 3];
1751  j += 4;
1752  }
1753 }
1754 
1761 void vpImageConvert::YUV411ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
1762 {
1763 #if 1
1764  // std::cout << "call optimized ConvertYUV411ToRGB()" << std::endl;
1765  for (unsigned int i = size / 4; i; i--) {
1766  int U = (int)((*yuv++ - 128) * 0.354);
1767  int U5 = 5 * U;
1768  int Y0 = *yuv++;
1769  int Y1 = *yuv++;
1770  int V = (int)((*yuv++ - 128) * 0.707);
1771  int V2 = 2 * V;
1772  int Y2 = *yuv++;
1773  int Y3 = *yuv++;
1774  int UV = -U - V;
1775 
1776  // Original equations
1777  // R = Y + 1.402 V
1778  // G = Y - 0.344 U - 0.714 V
1779  // B = Y + 1.772 U
1780  int R = Y0 + V2;
1781  if ((R >> 8) > 0)
1782  R = 255;
1783  else if (R < 0)
1784  R = 0;
1785 
1786  int G = Y0 + UV;
1787  if ((G >> 8) > 0)
1788  G = 255;
1789  else if (G < 0)
1790  G = 0;
1791 
1792  int B = Y0 + U5;
1793  if ((B >> 8) > 0)
1794  B = 255;
1795  else if (B < 0)
1796  B = 0;
1797 
1798  *rgb++ = (unsigned char)R;
1799  *rgb++ = (unsigned char)G;
1800  *rgb++ = (unsigned char)B;
1801 
1802  //---
1803  R = Y1 + V2;
1804  if ((R >> 8) > 0)
1805  R = 255;
1806  else if (R < 0)
1807  R = 0;
1808 
1809  G = Y1 + UV;
1810  if ((G >> 8) > 0)
1811  G = 255;
1812  else if (G < 0)
1813  G = 0;
1814 
1815  B = Y1 + U5;
1816  if ((B >> 8) > 0)
1817  B = 255;
1818  else if (B < 0)
1819  B = 0;
1820 
1821  *rgb++ = (unsigned char)R;
1822  *rgb++ = (unsigned char)G;
1823  *rgb++ = (unsigned char)B;
1824 
1825  //---
1826  R = Y2 + V2;
1827  if ((R >> 8) > 0)
1828  R = 255;
1829  else if (R < 0)
1830  R = 0;
1831 
1832  G = Y2 + UV;
1833  if ((G >> 8) > 0)
1834  G = 255;
1835  else if (G < 0)
1836  G = 0;
1837 
1838  B = Y2 + U5;
1839  if ((B >> 8) > 0)
1840  B = 255;
1841  else if (B < 0)
1842  B = 0;
1843 
1844  *rgb++ = (unsigned char)R;
1845  *rgb++ = (unsigned char)G;
1846  *rgb++ = (unsigned char)B;
1847 
1848  //---
1849  R = Y3 + V2;
1850  if ((R >> 8) > 0)
1851  R = 255;
1852  else if (R < 0)
1853  R = 0;
1854 
1855  G = Y3 + UV;
1856  if ((G >> 8) > 0)
1857  G = 255;
1858  else if (G < 0)
1859  G = 0;
1860 
1861  B = Y3 + U5;
1862  if ((B >> 8) > 0)
1863  B = 255;
1864  else if (B < 0)
1865  B = 0;
1866 
1867  *rgb++ = (unsigned char)R;
1868  *rgb++ = (unsigned char)G;
1869  *rgb++ = (unsigned char)B;
1870  }
1871 #else
1872  // tres tres lent ....
1873 
1874  unsigned int i = 0, j = 0;
1875  unsigned char r, g, b;
1876 
1877  while (j < size * 3 / 2) {
1878  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 3], r, g, b);
1879  rgb[i] = r;
1880  rgb[i + 1] = g;
1881  rgb[i + 2] = b;
1882  i += 3;
1883 
1884  YUVToRGB(yuv[j + 2], yuv[j], yuv[j + 3], r, g, b);
1885  rgb[i] = r;
1886  rgb[i + 1] = g;
1887  rgb[i + 2] = b;
1888  i += 3;
1889 
1890  YUVToRGB(yuv[j + 4], yuv[j], yuv[j + 3], r, g, b);
1891  rgb[i] = r;
1892  rgb[i + 1] = g;
1893  rgb[i + 2] = b;
1894  i += 3;
1895 
1896  YUVToRGB(yuv[j + 5], yuv[j], yuv[j + 3], r, g, b);
1897  rgb[i] = r;
1898  rgb[i + 1] = g;
1899  rgb[i + 2] = b;
1900  i += 3;
1901  // TRACE("r= %d g=%d b=%d", r, g, b);
1902 
1903  j += 6;
1904  }
1905 #endif
1906 }
1907 
1915 void vpImageConvert::YUV420ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
1916 {
1917  // std::cout << "call optimized ConvertYUV420ToRGBa()" << std::endl;
1918  int U, V, R, G, B, V2, U5, UV;
1919  int Y0, Y1, Y2, Y3;
1920  unsigned int size = width * height;
1921  unsigned char *iU = yuv + size;
1922  unsigned char *iV = yuv + 5 * size / 4;
1923  for (unsigned int i = 0; i < height / 2; i++) {
1924  for (unsigned int j = 0; j < width / 2; j++) {
1925  U = (int)((*iU++ - 128) * 0.354);
1926  U5 = 5 * U;
1927  V = (int)((*iV++ - 128) * 0.707);
1928  V2 = 2 * V;
1929  UV = -U - V;
1930  Y0 = *yuv++;
1931  Y1 = *yuv;
1932  yuv = yuv + width - 1;
1933  Y2 = *yuv++;
1934  Y3 = *yuv;
1935  yuv = yuv - width + 1;
1936 
1937  // Original equations
1938  // R = Y + 1.402 V
1939  // G = Y - 0.344 U - 0.714 V
1940  // B = Y + 1.772 U
1941  R = Y0 + V2;
1942  if ((R >> 8) > 0)
1943  R = 255;
1944  else if (R < 0)
1945  R = 0;
1946 
1947  G = Y0 + UV;
1948  if ((G >> 8) > 0)
1949  G = 255;
1950  else if (G < 0)
1951  G = 0;
1952 
1953  B = Y0 + U5;
1954  if ((B >> 8) > 0)
1955  B = 255;
1956  else if (B < 0)
1957  B = 0;
1958 
1959  *rgba++ = (unsigned char)R;
1960  *rgba++ = (unsigned char)G;
1961  *rgba++ = (unsigned char)B;
1962  *rgba++ = vpRGBa::alpha_default;
1963 
1964  //---
1965  R = Y1 + V2;
1966  if ((R >> 8) > 0)
1967  R = 255;
1968  else if (R < 0)
1969  R = 0;
1970 
1971  G = Y1 + UV;
1972  if ((G >> 8) > 0)
1973  G = 255;
1974  else if (G < 0)
1975  G = 0;
1976 
1977  B = Y1 + U5;
1978  if ((B >> 8) > 0)
1979  B = 255;
1980  else if (B < 0)
1981  B = 0;
1982 
1983  *rgba++ = (unsigned char)R;
1984  *rgba++ = (unsigned char)G;
1985  *rgba++ = (unsigned char)B;
1986  *rgba = vpRGBa::alpha_default;
1987  rgba = rgba + 4 * width - 7;
1988 
1989  //---
1990  R = Y2 + V2;
1991  if ((R >> 8) > 0)
1992  R = 255;
1993  else if (R < 0)
1994  R = 0;
1995 
1996  G = Y2 + UV;
1997  if ((G >> 8) > 0)
1998  G = 255;
1999  else if (G < 0)
2000  G = 0;
2001 
2002  B = Y2 + U5;
2003  if ((B >> 8) > 0)
2004  B = 255;
2005  else if (B < 0)
2006  B = 0;
2007 
2008  *rgba++ = (unsigned char)R;
2009  *rgba++ = (unsigned char)G;
2010  *rgba++ = (unsigned char)B;
2011  *rgba++ = vpRGBa::alpha_default;
2012 
2013  //---
2014  R = Y3 + V2;
2015  if ((R >> 8) > 0)
2016  R = 255;
2017  else if (R < 0)
2018  R = 0;
2019 
2020  G = Y3 + UV;
2021  if ((G >> 8) > 0)
2022  G = 255;
2023  else if (G < 0)
2024  G = 0;
2025 
2026  B = Y3 + U5;
2027  if ((B >> 8) > 0)
2028  B = 255;
2029  else if (B < 0)
2030  B = 0;
2031 
2032  *rgba++ = (unsigned char)R;
2033  *rgba++ = (unsigned char)G;
2034  *rgba++ = (unsigned char)B;
2035  *rgba = vpRGBa::alpha_default;
2036  rgba = rgba - 4 * width + 1;
2037  }
2038  yuv += width;
2039  rgba += 4 * width;
2040  }
2041 }
2047 void vpImageConvert::YUV420ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
2048 {
2049  // std::cout << "call optimized ConvertYUV420ToRGB()" << std::endl;
2050  int U, V, R, G, B, V2, U5, UV;
2051  int Y0, Y1, Y2, Y3;
2052  unsigned int size = width * height;
2053  unsigned char *iU = yuv + size;
2054  unsigned char *iV = yuv + 5 * size / 4;
2055  for (unsigned int i = 0; i < height / 2; i++) {
2056  for (unsigned int j = 0; j < width / 2; j++) {
2057  U = (int)((*iU++ - 128) * 0.354);
2058  U5 = 5 * U;
2059  V = (int)((*iV++ - 128) * 0.707);
2060  V2 = 2 * V;
2061  UV = -U - V;
2062  Y0 = *yuv++;
2063  Y1 = *yuv;
2064  yuv = yuv + width - 1;
2065  Y2 = *yuv++;
2066  Y3 = *yuv;
2067  yuv = yuv - width + 1;
2068 
2069  // Original equations
2070  // R = Y + 1.402 V
2071  // G = Y - 0.344 U - 0.714 V
2072  // B = Y + 1.772 U
2073  R = Y0 + V2;
2074  if ((R >> 8) > 0)
2075  R = 255;
2076  else if (R < 0)
2077  R = 0;
2078 
2079  G = Y0 + UV;
2080  if ((G >> 8) > 0)
2081  G = 255;
2082  else if (G < 0)
2083  G = 0;
2084 
2085  B = Y0 + U5;
2086  if ((B >> 8) > 0)
2087  B = 255;
2088  else if (B < 0)
2089  B = 0;
2090 
2091  *rgb++ = (unsigned char)R;
2092  *rgb++ = (unsigned char)G;
2093  *rgb++ = (unsigned char)B;
2094 
2095  //---
2096  R = Y1 + V2;
2097  if ((R >> 8) > 0)
2098  R = 255;
2099  else if (R < 0)
2100  R = 0;
2101 
2102  G = Y1 + UV;
2103  if ((G >> 8) > 0)
2104  G = 255;
2105  else if (G < 0)
2106  G = 0;
2107 
2108  B = Y1 + U5;
2109  if ((B >> 8) > 0)
2110  B = 255;
2111  else if (B < 0)
2112  B = 0;
2113 
2114  *rgb++ = (unsigned char)R;
2115  *rgb++ = (unsigned char)G;
2116  *rgb = (unsigned char)B;
2117  rgb = rgb + 3 * width - 5;
2118 
2119  //---
2120  R = Y2 + V2;
2121  if ((R >> 8) > 0)
2122  R = 255;
2123  else if (R < 0)
2124  R = 0;
2125 
2126  G = Y2 + UV;
2127  if ((G >> 8) > 0)
2128  G = 255;
2129  else if (G < 0)
2130  G = 0;
2131 
2132  B = Y2 + U5;
2133  if ((B >> 8) > 0)
2134  B = 255;
2135  else if (B < 0)
2136  B = 0;
2137 
2138  *rgb++ = (unsigned char)R;
2139  *rgb++ = (unsigned char)G;
2140  *rgb++ = (unsigned char)B;
2141 
2142  //---
2143  R = Y3 + V2;
2144  if ((R >> 8) > 0)
2145  R = 255;
2146  else if (R < 0)
2147  R = 0;
2148 
2149  G = Y3 + UV;
2150  if ((G >> 8) > 0)
2151  G = 255;
2152  else if (G < 0)
2153  G = 0;
2154 
2155  B = Y3 + U5;
2156  if ((B >> 8) > 0)
2157  B = 255;
2158  else if (B < 0)
2159  B = 0;
2160 
2161  *rgb++ = (unsigned char)R;
2162  *rgb++ = (unsigned char)G;
2163  *rgb = (unsigned char)B;
2164  rgb = rgb - 3 * width + 1;
2165  }
2166  yuv += width;
2167  rgb += 3 * width;
2168  }
2169 }
2170 
2176 void vpImageConvert::YUV420ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
2177 {
2178  for (unsigned int i = 0; i < size; i++) {
2179  *grey++ = *yuv++;
2180  }
2181 }
2189 void vpImageConvert::YUV444ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
2190 {
2191  for (unsigned int i = 0; i < size; i++) {
2192  int U = (int)((*yuv++ - 128) * 0.354);
2193  int U5 = 5 * U;
2194  int Y = *yuv++;
2195  int V = (int)((*yuv++ - 128) * 0.707);
2196  int V2 = 2 * V;
2197  int UV = -U - V;
2198 
2199  // Original equations
2200  // R = Y + 1.402 V
2201  // G = Y - 0.344 U - 0.714 V
2202  // B = Y + 1.772 U
2203  int R = Y + V2;
2204  if ((R >> 8) > 0)
2205  R = 255;
2206  else if (R < 0)
2207  R = 0;
2208 
2209  int G = Y + UV;
2210  if ((G >> 8) > 0)
2211  G = 255;
2212  else if (G < 0)
2213  G = 0;
2214 
2215  int B = Y + U5;
2216  if ((B >> 8) > 0)
2217  B = 255;
2218  else if (B < 0)
2219  B = 0;
2220 
2221  *rgba++ = (unsigned char)R;
2222  *rgba++ = (unsigned char)G;
2223  *rgba++ = (unsigned char)B;
2224  *rgba++ = vpRGBa::alpha_default;
2225  }
2226 }
2232 void vpImageConvert::YUV444ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
2233 {
2234  for (unsigned int i = 0; i < size; i++) {
2235  int U = (int)((*yuv++ - 128) * 0.354);
2236  int U5 = 5 * U;
2237  int Y = *yuv++;
2238  int V = (int)((*yuv++ - 128) * 0.707);
2239  int V2 = 2 * V;
2240  int UV = -U - V;
2241 
2242  // Original equations
2243  // R = Y + 1.402 V
2244  // G = Y - 0.344 U - 0.714 V
2245  // B = Y + 1.772 U
2246  int R = Y + V2;
2247  if ((R >> 8) > 0)
2248  R = 255;
2249  else if (R < 0)
2250  R = 0;
2251 
2252  int G = Y + UV;
2253  if ((G >> 8) > 0)
2254  G = 255;
2255  else if (G < 0)
2256  G = 0;
2257 
2258  int B = Y + U5;
2259  if ((B >> 8) > 0)
2260  B = 255;
2261  else if (B < 0)
2262  B = 0;
2263 
2264  *rgb++ = (unsigned char)R;
2265  *rgb++ = (unsigned char)G;
2266  *rgb++ = (unsigned char)B;
2267  }
2268 }
2269 
2275 void vpImageConvert::YUV444ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
2276 {
2277  yuv++;
2278  for (unsigned int i = 0; i < size; i++) {
2279  *grey++ = *yuv;
2280  yuv = yuv + 3;
2281  }
2282 }
2283 
2291 void vpImageConvert::YV12ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
2292 {
2293  // std::cout << "call optimized ConvertYV12ToRGBa()" << std::endl;
2294  int U, V, R, G, B, V2, U5, UV;
2295  int Y0, Y1, Y2, Y3;
2296  unsigned int size = width * height;
2297  unsigned char *iV = yuv + size;
2298  unsigned char *iU = yuv + 5 * size / 4;
2299  for (unsigned int i = 0; i < height / 2; i++) {
2300  for (unsigned int j = 0; j < width / 2; j++) {
2301  U = (int)((*iU++ - 128) * 0.354);
2302  U5 = 5 * U;
2303  V = (int)((*iV++ - 128) * 0.707);
2304  V2 = 2 * V;
2305  UV = -U - V;
2306  Y0 = *yuv++;
2307  Y1 = *yuv;
2308  yuv = yuv + width - 1;
2309  Y2 = *yuv++;
2310  Y3 = *yuv;
2311  yuv = yuv - width + 1;
2312 
2313  // Original equations
2314  // R = Y + 1.402 V
2315  // G = Y - 0.344 U - 0.714 V
2316  // B = Y + 1.772 U
2317  R = Y0 + V2;
2318  if ((R >> 8) > 0)
2319  R = 255;
2320  else if (R < 0)
2321  R = 0;
2322 
2323  G = Y0 + UV;
2324  if ((G >> 8) > 0)
2325  G = 255;
2326  else if (G < 0)
2327  G = 0;
2328 
2329  B = Y0 + U5;
2330  if ((B >> 8) > 0)
2331  B = 255;
2332  else if (B < 0)
2333  B = 0;
2334 
2335  *rgba++ = (unsigned char)R;
2336  *rgba++ = (unsigned char)G;
2337  *rgba++ = (unsigned char)B;
2338  *rgba++ = vpRGBa::alpha_default;
2339 
2340  //---
2341  R = Y1 + V2;
2342  if ((R >> 8) > 0)
2343  R = 255;
2344  else if (R < 0)
2345  R = 0;
2346 
2347  G = Y1 + UV;
2348  if ((G >> 8) > 0)
2349  G = 255;
2350  else if (G < 0)
2351  G = 0;
2352 
2353  B = Y1 + U5;
2354  if ((B >> 8) > 0)
2355  B = 255;
2356  else if (B < 0)
2357  B = 0;
2358 
2359  *rgba++ = (unsigned char)R;
2360  *rgba++ = (unsigned char)G;
2361  *rgba++ = (unsigned char)B;
2362  *rgba = 0;
2363  rgba = rgba + 4 * width - 7;
2364 
2365  //---
2366  R = Y2 + V2;
2367  if ((R >> 8) > 0)
2368  R = 255;
2369  else if (R < 0)
2370  R = 0;
2371 
2372  G = Y2 + UV;
2373  if ((G >> 8) > 0)
2374  G = 255;
2375  else if (G < 0)
2376  G = 0;
2377 
2378  B = Y2 + U5;
2379  if ((B >> 8) > 0)
2380  B = 255;
2381  else if (B < 0)
2382  B = 0;
2383 
2384  *rgba++ = (unsigned char)R;
2385  *rgba++ = (unsigned char)G;
2386  *rgba++ = (unsigned char)B;
2387  *rgba++ = vpRGBa::alpha_default;
2388 
2389  //---
2390  R = Y3 + V2;
2391  if ((R >> 8) > 0)
2392  R = 255;
2393  else if (R < 0)
2394  R = 0;
2395 
2396  G = Y3 + UV;
2397  if ((G >> 8) > 0)
2398  G = 255;
2399  else if (G < 0)
2400  G = 0;
2401 
2402  B = Y3 + U5;
2403  if ((B >> 8) > 0)
2404  B = 255;
2405  else if (B < 0)
2406  B = 0;
2407 
2408  *rgba++ = (unsigned char)R;
2409  *rgba++ = (unsigned char)G;
2410  *rgba++ = (unsigned char)B;
2411  *rgba = vpRGBa::alpha_default;
2412  rgba = rgba - 4 * width + 1;
2413  }
2414  yuv += width;
2415  rgba += 4 * width;
2416  }
2417 }
2423 void vpImageConvert::YV12ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int height, unsigned int width)
2424 {
2425  // std::cout << "call optimized ConvertYV12ToRGB()" << std::endl;
2426  int U, V, R, G, B, V2, U5, UV;
2427  int Y0, Y1, Y2, Y3;
2428  unsigned int size = width * height;
2429  unsigned char *iV = yuv + size;
2430  unsigned char *iU = yuv + 5 * size / 4;
2431  for (unsigned int i = 0; i < height / 2; i++) {
2432  for (unsigned int j = 0; j < width / 2; j++) {
2433  U = (int)((*iU++ - 128) * 0.354);
2434  U5 = 5 * U;
2435  V = (int)((*iV++ - 128) * 0.707);
2436  V2 = 2 * V;
2437  UV = -U - V;
2438  Y0 = *yuv++;
2439  Y1 = *yuv;
2440  yuv = yuv + width - 1;
2441  Y2 = *yuv++;
2442  Y3 = *yuv;
2443  yuv = yuv - width + 1;
2444 
2445  // Original equations
2446  // R = Y + 1.402 V
2447  // G = Y - 0.344 U - 0.714 V
2448  // B = Y + 1.772 U
2449  R = Y0 + V2;
2450  if ((R >> 8) > 0)
2451  R = 255;
2452  else if (R < 0)
2453  R = 0;
2454 
2455  G = Y0 + UV;
2456  if ((G >> 8) > 0)
2457  G = 255;
2458  else if (G < 0)
2459  G = 0;
2460 
2461  B = Y0 + U5;
2462  if ((B >> 8) > 0)
2463  B = 255;
2464  else if (B < 0)
2465  B = 0;
2466 
2467  *rgb++ = (unsigned char)R;
2468  *rgb++ = (unsigned char)G;
2469  *rgb++ = (unsigned char)B;
2470 
2471  //---
2472  R = Y1 + V2;
2473  if ((R >> 8) > 0)
2474  R = 255;
2475  else if (R < 0)
2476  R = 0;
2477 
2478  G = Y1 + UV;
2479  if ((G >> 8) > 0)
2480  G = 255;
2481  else if (G < 0)
2482  G = 0;
2483 
2484  B = Y1 + U5;
2485  if ((B >> 8) > 0)
2486  B = 255;
2487  else if (B < 0)
2488  B = 0;
2489 
2490  *rgb++ = (unsigned char)R;
2491  *rgb++ = (unsigned char)G;
2492  *rgb = (unsigned char)B;
2493  rgb = rgb + 3 * width - 5;
2494 
2495  //---
2496  R = Y2 + V2;
2497  if ((R >> 8) > 0)
2498  R = 255;
2499  else if (R < 0)
2500  R = 0;
2501 
2502  G = Y2 + UV;
2503  if ((G >> 8) > 0)
2504  G = 255;
2505  else if (G < 0)
2506  G = 0;
2507 
2508  B = Y2 + U5;
2509  if ((B >> 8) > 0)
2510  B = 255;
2511  else if (B < 0)
2512  B = 0;
2513 
2514  *rgb++ = (unsigned char)R;
2515  *rgb++ = (unsigned char)G;
2516  *rgb++ = (unsigned char)B;
2517 
2518  //---
2519  R = Y3 + V2;
2520  if ((R >> 8) > 0)
2521  R = 255;
2522  else if (R < 0)
2523  R = 0;
2524 
2525  G = Y3 + UV;
2526  if ((G >> 8) > 0)
2527  G = 255;
2528  else if (G < 0)
2529  G = 0;
2530 
2531  B = Y3 + U5;
2532  if ((B >> 8) > 0)
2533  B = 255;
2534  else if (B < 0)
2535  B = 0;
2536 
2537  *rgb++ = (unsigned char)R;
2538  *rgb++ = (unsigned char)G;
2539  *rgb = (unsigned char)B;
2540  rgb = rgb - 3 * width + 1;
2541  }
2542  yuv += width;
2543  rgb += 3 * width;
2544  }
2545 }
2546 
2554 void vpImageConvert::YVU9ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
2555 {
2556  // std::cout << "call optimized ConvertYVU9ToRGBa()" << std::endl;
2557  int U, V, R, G, B, V2, U5, UV;
2558  int Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9, Y10, Y11, Y12, Y13, Y14, Y15;
2559  unsigned int size = width * height;
2560  unsigned char *iV = yuv + size;
2561  unsigned char *iU = yuv + 17 * size / 16;
2562  for (unsigned int i = 0; i < height / 4; i++) {
2563  for (unsigned int j = 0; j < width / 4; j++) {
2564  U = (int)((*iU++ - 128) * 0.354);
2565  U5 = 5 * U;
2566  V = (int)((*iV++ - 128) * 0.707);
2567  V2 = 2 * V;
2568  UV = -U - V;
2569  Y0 = *yuv++;
2570  Y1 = *yuv++;
2571  Y2 = *yuv++;
2572  Y3 = *yuv;
2573  yuv = yuv + width - 3;
2574  Y4 = *yuv++;
2575  Y5 = *yuv++;
2576  Y6 = *yuv++;
2577  Y7 = *yuv;
2578  yuv = yuv + width - 3;
2579  Y8 = *yuv++;
2580  Y9 = *yuv++;
2581  Y10 = *yuv++;
2582  Y11 = *yuv;
2583  yuv = yuv + width - 3;
2584  Y12 = *yuv++;
2585  Y13 = *yuv++;
2586  Y14 = *yuv++;
2587  Y15 = *yuv;
2588  yuv = yuv - 3 * width + 1;
2589 
2590  // Original equations
2591  // R = Y + 1.402 V
2592  // G = Y - 0.344 U - 0.714 V
2593  // B = Y + 1.772 U
2594  R = Y0 + V2;
2595  if ((R >> 8) > 0)
2596  R = 255;
2597  else if (R < 0)
2598  R = 0;
2599 
2600  G = Y0 + UV;
2601  if ((G >> 8) > 0)
2602  G = 255;
2603  else if (G < 0)
2604  G = 0;
2605 
2606  B = Y0 + U5;
2607  if ((B >> 8) > 0)
2608  B = 255;
2609  else if (B < 0)
2610  B = 0;
2611 
2612  *rgba++ = (unsigned char)R;
2613  *rgba++ = (unsigned char)G;
2614  *rgba++ = (unsigned char)B;
2615  *rgba++ = vpRGBa::alpha_default;
2616 
2617  //---
2618  R = Y1 + V2;
2619  if ((R >> 8) > 0)
2620  R = 255;
2621  else if (R < 0)
2622  R = 0;
2623 
2624  G = Y1 + UV;
2625  if ((G >> 8) > 0)
2626  G = 255;
2627  else if (G < 0)
2628  G = 0;
2629 
2630  B = Y1 + U5;
2631  if ((B >> 8) > 0)
2632  B = 255;
2633  else if (B < 0)
2634  B = 0;
2635 
2636  *rgba++ = (unsigned char)R;
2637  *rgba++ = (unsigned char)G;
2638  *rgba++ = (unsigned char)B;
2639  *rgba++ = vpRGBa::alpha_default;
2640 
2641  //---
2642  R = Y2 + V2;
2643  if ((R >> 8) > 0)
2644  R = 255;
2645  else if (R < 0)
2646  R = 0;
2647 
2648  G = Y2 + UV;
2649  if ((G >> 8) > 0)
2650  G = 255;
2651  else if (G < 0)
2652  G = 0;
2653 
2654  B = Y2 + U5;
2655  if ((B >> 8) > 0)
2656  B = 255;
2657  else if (B < 0)
2658  B = 0;
2659 
2660  *rgba++ = (unsigned char)R;
2661  *rgba++ = (unsigned char)G;
2662  *rgba++ = (unsigned char)B;
2663  *rgba++ = vpRGBa::alpha_default;
2664 
2665  //---
2666  R = Y3 + V2;
2667  if ((R >> 8) > 0)
2668  R = 255;
2669  else if (R < 0)
2670  R = 0;
2671 
2672  G = Y3 + UV;
2673  if ((G >> 8) > 0)
2674  G = 255;
2675  else if (G < 0)
2676  G = 0;
2677 
2678  B = Y3 + U5;
2679  if ((B >> 8) > 0)
2680  B = 255;
2681  else if (B < 0)
2682  B = 0;
2683 
2684  *rgba++ = (unsigned char)R;
2685  *rgba++ = (unsigned char)G;
2686  *rgba++ = (unsigned char)B;
2687  *rgba = vpRGBa::alpha_default;
2688  rgba = rgba + 4 * width - 15;
2689 
2690  R = Y4 + V2;
2691  if ((R >> 8) > 0)
2692  R = 255;
2693  else if (R < 0)
2694  R = 0;
2695 
2696  G = Y4 + UV;
2697  if ((G >> 8) > 0)
2698  G = 255;
2699  else if (G < 0)
2700  G = 0;
2701 
2702  B = Y4 + U5;
2703  if ((B >> 8) > 0)
2704  B = 255;
2705  else if (B < 0)
2706  B = 0;
2707 
2708  *rgba++ = (unsigned char)R;
2709  *rgba++ = (unsigned char)G;
2710  *rgba++ = (unsigned char)B;
2711  *rgba++ = vpRGBa::alpha_default;
2712 
2713  //---
2714  R = Y5 + V2;
2715  if ((R >> 8) > 0)
2716  R = 255;
2717  else if (R < 0)
2718  R = 0;
2719 
2720  G = Y5 + UV;
2721  if ((G >> 8) > 0)
2722  G = 255;
2723  else if (G < 0)
2724  G = 0;
2725 
2726  B = Y5 + U5;
2727  if ((B >> 8) > 0)
2728  B = 255;
2729  else if (B < 0)
2730  B = 0;
2731 
2732  *rgba++ = (unsigned char)R;
2733  *rgba++ = (unsigned char)G;
2734  *rgba++ = (unsigned char)B;
2735  *rgba++ = vpRGBa::alpha_default;
2736 
2737  //---
2738  R = Y6 + V2;
2739  if ((R >> 8) > 0)
2740  R = 255;
2741  else if (R < 0)
2742  R = 0;
2743 
2744  G = Y6 + UV;
2745  if ((G >> 8) > 0)
2746  G = 255;
2747  else if (G < 0)
2748  G = 0;
2749 
2750  B = Y6 + U5;
2751  if ((B >> 8) > 0)
2752  B = 255;
2753  else if (B < 0)
2754  B = 0;
2755 
2756  *rgba++ = (unsigned char)R;
2757  *rgba++ = (unsigned char)G;
2758  *rgba++ = (unsigned char)B;
2759  *rgba++ = vpRGBa::alpha_default;
2760 
2761  //---
2762  R = Y7 + V2;
2763  if ((R >> 8) > 0)
2764  R = 255;
2765  else if (R < 0)
2766  R = 0;
2767 
2768  G = Y7 + UV;
2769  if ((G >> 8) > 0)
2770  G = 255;
2771  else if (G < 0)
2772  G = 0;
2773 
2774  B = Y7 + U5;
2775  if ((B >> 8) > 0)
2776  B = 255;
2777  else if (B < 0)
2778  B = 0;
2779 
2780  *rgba++ = (unsigned char)R;
2781  *rgba++ = (unsigned char)G;
2782  *rgba++ = (unsigned char)B;
2783  *rgba = vpRGBa::alpha_default;
2784  rgba = rgba + 4 * width - 15;
2785 
2786  R = Y8 + V2;
2787  if ((R >> 8) > 0)
2788  R = 255;
2789  else if (R < 0)
2790  R = 0;
2791 
2792  G = Y8 + UV;
2793  if ((G >> 8) > 0)
2794  G = 255;
2795  else if (G < 0)
2796  G = 0;
2797 
2798  B = Y8 + U5;
2799  if ((B >> 8) > 0)
2800  B = 255;
2801  else if (B < 0)
2802  B = 0;
2803 
2804  *rgba++ = (unsigned char)R;
2805  *rgba++ = (unsigned char)G;
2806  *rgba++ = (unsigned char)B;
2807  *rgba++ = vpRGBa::alpha_default;
2808 
2809  //---
2810  R = Y9 + V2;
2811  if ((R >> 8) > 0)
2812  R = 255;
2813  else if (R < 0)
2814  R = 0;
2815 
2816  G = Y9 + UV;
2817  if ((G >> 8) > 0)
2818  G = 255;
2819  else if (G < 0)
2820  G = 0;
2821 
2822  B = Y9 + U5;
2823  if ((B >> 8) > 0)
2824  B = 255;
2825  else if (B < 0)
2826  B = 0;
2827 
2828  *rgba++ = (unsigned char)R;
2829  *rgba++ = (unsigned char)G;
2830  *rgba++ = (unsigned char)B;
2831  *rgba++ = vpRGBa::alpha_default;
2832 
2833  //---
2834  R = Y10 + V2;
2835  if ((R >> 8) > 0)
2836  R = 255;
2837  else if (R < 0)
2838  R = 0;
2839 
2840  G = Y10 + UV;
2841  if ((G >> 8) > 0)
2842  G = 255;
2843  else if (G < 0)
2844  G = 0;
2845 
2846  B = Y10 + U5;
2847  if ((B >> 8) > 0)
2848  B = 255;
2849  else if (B < 0)
2850  B = 0;
2851 
2852  *rgba++ = (unsigned char)R;
2853  *rgba++ = (unsigned char)G;
2854  *rgba++ = (unsigned char)B;
2855  *rgba++ = vpRGBa::alpha_default;
2856 
2857  //---
2858  R = Y11 + V2;
2859  if ((R >> 8) > 0)
2860  R = 255;
2861  else if (R < 0)
2862  R = 0;
2863 
2864  G = Y11 + UV;
2865  if ((G >> 8) > 0)
2866  G = 255;
2867  else if (G < 0)
2868  G = 0;
2869 
2870  B = Y11 + U5;
2871  if ((B >> 8) > 0)
2872  B = 255;
2873  else if (B < 0)
2874  B = 0;
2875 
2876  *rgba++ = (unsigned char)R;
2877  *rgba++ = (unsigned char)G;
2878  *rgba++ = (unsigned char)B;
2879  *rgba = vpRGBa::alpha_default;
2880  rgba = rgba + 4 * width - 15;
2881 
2882  R = Y12 + V2;
2883  if ((R >> 8) > 0)
2884  R = 255;
2885  else if (R < 0)
2886  R = 0;
2887 
2888  G = Y12 + UV;
2889  if ((G >> 8) > 0)
2890  G = 255;
2891  else if (G < 0)
2892  G = 0;
2893 
2894  B = Y12 + U5;
2895  if ((B >> 8) > 0)
2896  B = 255;
2897  else if (B < 0)
2898  B = 0;
2899 
2900  *rgba++ = (unsigned char)R;
2901  *rgba++ = (unsigned char)G;
2902  *rgba++ = (unsigned char)B;
2903  *rgba++ = vpRGBa::alpha_default;
2904 
2905  //---
2906  R = Y13 + V2;
2907  if ((R >> 8) > 0)
2908  R = 255;
2909  else if (R < 0)
2910  R = 0;
2911 
2912  G = Y13 + UV;
2913  if ((G >> 8) > 0)
2914  G = 255;
2915  else if (G < 0)
2916  G = 0;
2917 
2918  B = Y13 + U5;
2919  if ((B >> 8) > 0)
2920  B = 255;
2921  else if (B < 0)
2922  B = 0;
2923 
2924  *rgba++ = (unsigned char)R;
2925  *rgba++ = (unsigned char)G;
2926  *rgba++ = (unsigned char)B;
2927  *rgba++ = vpRGBa::alpha_default;
2928 
2929  //---
2930  R = Y14 + V2;
2931  if ((R >> 8) > 0)
2932  R = 255;
2933  else if (R < 0)
2934  R = 0;
2935 
2936  G = Y14 + UV;
2937  if ((G >> 8) > 0)
2938  G = 255;
2939  else if (G < 0)
2940  G = 0;
2941 
2942  B = Y14 + U5;
2943  if ((B >> 8) > 0)
2944  B = 255;
2945  else if (B < 0)
2946  B = 0;
2947 
2948  *rgba++ = (unsigned char)R;
2949  *rgba++ = (unsigned char)G;
2950  *rgba++ = (unsigned char)B;
2951  *rgba++ = vpRGBa::alpha_default;
2952 
2953  //---
2954  R = Y15 + V2;
2955  if ((R >> 8) > 0)
2956  R = 255;
2957  else if (R < 0)
2958  R = 0;
2959 
2960  G = Y15 + UV;
2961  if ((G >> 8) > 0)
2962  G = 255;
2963  else if (G < 0)
2964  G = 0;
2965 
2966  B = Y15 + U5;
2967  if ((B >> 8) > 0)
2968  B = 255;
2969  else if (B < 0)
2970  B = 0;
2971 
2972  *rgba++ = (unsigned char)R;
2973  *rgba++ = (unsigned char)G;
2974  *rgba++ = (unsigned char)B;
2975  *rgba = vpRGBa::alpha_default;
2976  rgba = rgba - 12 * width + 1;
2977  }
2978  yuv += 3 * width;
2979  rgba += 12 * width;
2980  }
2981 }
2987 void vpImageConvert::YVU9ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int height, unsigned int width)
2988 {
2989  // std::cout << "call optimized ConvertYVU9ToRGB()" << std::endl;
2990  int U, V, R, G, B, V2, U5, UV;
2991  int Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9, Y10, Y11, Y12, Y13, Y14, Y15;
2992  unsigned int size = width * height;
2993  unsigned char *iV = yuv + size;
2994  unsigned char *iU = yuv + 17 * size / 16;
2995  for (unsigned int i = 0; i < height / 4; i++) {
2996  for (unsigned int j = 0; j < width / 4; j++) {
2997  U = (int)((*iU++ - 128) * 0.354);
2998  U5 = 5 * U;
2999  V = (int)((*iV++ - 128) * 0.707);
3000  V2 = 2 * V;
3001  UV = -U - V;
3002  Y0 = *yuv++;
3003  Y1 = *yuv++;
3004  Y2 = *yuv++;
3005  Y3 = *yuv;
3006  yuv = yuv + width - 3;
3007  Y4 = *yuv++;
3008  Y5 = *yuv++;
3009  Y6 = *yuv++;
3010  Y7 = *yuv;
3011  yuv = yuv + width - 3;
3012  Y8 = *yuv++;
3013  Y9 = *yuv++;
3014  Y10 = *yuv++;
3015  Y11 = *yuv;
3016  yuv = yuv + width - 3;
3017  Y12 = *yuv++;
3018  Y13 = *yuv++;
3019  Y14 = *yuv++;
3020  Y15 = *yuv;
3021  yuv = yuv - 3 * width + 1;
3022 
3023  // Original equations
3024  // R = Y + 1.402 V
3025  // G = Y - 0.344 U - 0.714 V
3026  // B = Y + 1.772 U
3027  R = Y0 + V2;
3028  if ((R >> 8) > 0)
3029  R = 255;
3030  else if (R < 0)
3031  R = 0;
3032 
3033  G = Y0 + UV;
3034  if ((G >> 8) > 0)
3035  G = 255;
3036  else if (G < 0)
3037  G = 0;
3038 
3039  B = Y0 + U5;
3040  if ((B >> 8) > 0)
3041  B = 255;
3042  else if (B < 0)
3043  B = 0;
3044 
3045  *rgb++ = (unsigned char)R;
3046  *rgb++ = (unsigned char)G;
3047  *rgb++ = (unsigned char)B;
3048 
3049  //---
3050  R = Y1 + V2;
3051  if ((R >> 8) > 0)
3052  R = 255;
3053  else if (R < 0)
3054  R = 0;
3055 
3056  G = Y1 + UV;
3057  if ((G >> 8) > 0)
3058  G = 255;
3059  else if (G < 0)
3060  G = 0;
3061 
3062  B = Y1 + U5;
3063  if ((B >> 8) > 0)
3064  B = 255;
3065  else if (B < 0)
3066  B = 0;
3067 
3068  *rgb++ = (unsigned char)R;
3069  *rgb++ = (unsigned char)G;
3070  *rgb++ = (unsigned char)B;
3071 
3072  //---
3073  R = Y2 + V2;
3074  if ((R >> 8) > 0)
3075  R = 255;
3076  else if (R < 0)
3077  R = 0;
3078 
3079  G = Y2 + UV;
3080  if ((G >> 8) > 0)
3081  G = 255;
3082  else if (G < 0)
3083  G = 0;
3084 
3085  B = Y2 + U5;
3086  if ((B >> 8) > 0)
3087  B = 255;
3088  else if (B < 0)
3089  B = 0;
3090 
3091  *rgb++ = (unsigned char)R;
3092  *rgb++ = (unsigned char)G;
3093  *rgb++ = (unsigned char)B;
3094 
3095  //---
3096  R = Y3 + V2;
3097  if ((R >> 8) > 0)
3098  R = 255;
3099  else if (R < 0)
3100  R = 0;
3101 
3102  G = Y3 + UV;
3103  if ((G >> 8) > 0)
3104  G = 255;
3105  else if (G < 0)
3106  G = 0;
3107 
3108  B = Y3 + U5;
3109  if ((B >> 8) > 0)
3110  B = 255;
3111  else if (B < 0)
3112  B = 0;
3113 
3114  *rgb++ = (unsigned char)R;
3115  *rgb++ = (unsigned char)G;
3116  *rgb = (unsigned char)B;
3117  rgb = rgb + 3 * width - 11;
3118 
3119  R = Y4 + V2;
3120  if ((R >> 8) > 0)
3121  R = 255;
3122  else if (R < 0)
3123  R = 0;
3124 
3125  G = Y4 + UV;
3126  if ((G >> 8) > 0)
3127  G = 255;
3128  else if (G < 0)
3129  G = 0;
3130 
3131  B = Y4 + U5;
3132  if ((B >> 8) > 0)
3133  B = 255;
3134  else if (B < 0)
3135  B = 0;
3136 
3137  *rgb++ = (unsigned char)R;
3138  *rgb++ = (unsigned char)G;
3139  *rgb++ = (unsigned char)B;
3140 
3141  //---
3142  R = Y5 + V2;
3143  if ((R >> 8) > 0)
3144  R = 255;
3145  else if (R < 0)
3146  R = 0;
3147 
3148  G = Y5 + UV;
3149  if ((G >> 8) > 0)
3150  G = 255;
3151  else if (G < 0)
3152  G = 0;
3153 
3154  B = Y5 + U5;
3155  if ((B >> 8) > 0)
3156  B = 255;
3157  else if (B < 0)
3158  B = 0;
3159 
3160  *rgb++ = (unsigned char)R;
3161  *rgb++ = (unsigned char)G;
3162  *rgb++ = (unsigned char)B;
3163 
3164  //---
3165  R = Y6 + V2;
3166  if ((R >> 8) > 0)
3167  R = 255;
3168  else if (R < 0)
3169  R = 0;
3170 
3171  G = Y6 + UV;
3172  if ((G >> 8) > 0)
3173  G = 255;
3174  else if (G < 0)
3175  G = 0;
3176 
3177  B = Y6 + U5;
3178  if ((B >> 8) > 0)
3179  B = 255;
3180  else if (B < 0)
3181  B = 0;
3182 
3183  *rgb++ = (unsigned char)R;
3184  *rgb++ = (unsigned char)G;
3185  *rgb++ = (unsigned char)B;
3186 
3187  //---
3188  R = Y7 + V2;
3189  if ((R >> 8) > 0)
3190  R = 255;
3191  else if (R < 0)
3192  R = 0;
3193 
3194  G = Y7 + UV;
3195  if ((G >> 8) > 0)
3196  G = 255;
3197  else if (G < 0)
3198  G = 0;
3199 
3200  B = Y7 + U5;
3201  if ((B >> 8) > 0)
3202  B = 255;
3203  else if (B < 0)
3204  B = 0;
3205 
3206  *rgb++ = (unsigned char)R;
3207  *rgb++ = (unsigned char)G;
3208  *rgb = (unsigned char)B;
3209  rgb = rgb + 3 * width - 11;
3210 
3211  R = Y8 + V2;
3212  if ((R >> 8) > 0)
3213  R = 255;
3214  else if (R < 0)
3215  R = 0;
3216 
3217  G = Y8 + UV;
3218  if ((G >> 8) > 0)
3219  G = 255;
3220  else if (G < 0)
3221  G = 0;
3222 
3223  B = Y8 + U5;
3224  if ((B >> 8) > 0)
3225  B = 255;
3226  else if (B < 0)
3227  B = 0;
3228 
3229  *rgb++ = (unsigned char)R;
3230  *rgb++ = (unsigned char)G;
3231  *rgb++ = (unsigned char)B;
3232 
3233  //---
3234  R = Y9 + V2;
3235  if ((R >> 8) > 0)
3236  R = 255;
3237  else if (R < 0)
3238  R = 0;
3239 
3240  G = Y9 + UV;
3241  if ((G >> 8) > 0)
3242  G = 255;
3243  else if (G < 0)
3244  G = 0;
3245 
3246  B = Y9 + U5;
3247  if ((B >> 8) > 0)
3248  B = 255;
3249  else if (B < 0)
3250  B = 0;
3251 
3252  *rgb++ = (unsigned char)R;
3253  *rgb++ = (unsigned char)G;
3254  *rgb++ = (unsigned char)B;
3255 
3256  //---
3257  R = Y10 + V2;
3258  if ((R >> 8) > 0)
3259  R = 255;
3260  else if (R < 0)
3261  R = 0;
3262 
3263  G = Y10 + UV;
3264  if ((G >> 8) > 0)
3265  G = 255;
3266  else if (G < 0)
3267  G = 0;
3268 
3269  B = Y10 + U5;
3270  if ((B >> 8) > 0)
3271  B = 255;
3272  else if (B < 0)
3273  B = 0;
3274 
3275  *rgb++ = (unsigned char)R;
3276  *rgb++ = (unsigned char)G;
3277  *rgb++ = (unsigned char)B;
3278 
3279  //---
3280  R = Y11 + V2;
3281  if ((R >> 8) > 0)
3282  R = 255;
3283  else if (R < 0)
3284  R = 0;
3285 
3286  G = Y11 + UV;
3287  if ((G >> 8) > 0)
3288  G = 255;
3289  else if (G < 0)
3290  G = 0;
3291 
3292  B = Y11 + U5;
3293  if ((B >> 8) > 0)
3294  B = 255;
3295  else if (B < 0)
3296  B = 0;
3297 
3298  *rgb++ = (unsigned char)R;
3299  *rgb++ = (unsigned char)G;
3300  *rgb = (unsigned char)B;
3301  rgb = rgb + 3 * width - 11;
3302 
3303  R = Y12 + V2;
3304  if ((R >> 8) > 0)
3305  R = 255;
3306  else if (R < 0)
3307  R = 0;
3308 
3309  G = Y12 + UV;
3310  if ((G >> 8) > 0)
3311  G = 255;
3312  else if (G < 0)
3313  G = 0;
3314 
3315  B = Y12 + U5;
3316  if ((B >> 8) > 0)
3317  B = 255;
3318  else if (B < 0)
3319  B = 0;
3320 
3321  *rgb++ = (unsigned char)R;
3322  *rgb++ = (unsigned char)G;
3323  *rgb++ = (unsigned char)B;
3324 
3325  //---
3326  R = Y13 + V2;
3327  if ((R >> 8) > 0)
3328  R = 255;
3329  else if (R < 0)
3330  R = 0;
3331 
3332  G = Y13 + UV;
3333  if ((G >> 8) > 0)
3334  G = 255;
3335  else if (G < 0)
3336  G = 0;
3337 
3338  B = Y13 + U5;
3339  if ((B >> 8) > 0)
3340  B = 255;
3341  else if (B < 0)
3342  B = 0;
3343 
3344  *rgb++ = (unsigned char)R;
3345  *rgb++ = (unsigned char)G;
3346  *rgb++ = (unsigned char)B;
3347 
3348  //---
3349  R = Y14 + V2;
3350  if ((R >> 8) > 0)
3351  R = 255;
3352  else if (R < 0)
3353  R = 0;
3354 
3355  G = Y14 + UV;
3356  if ((G >> 8) > 0)
3357  G = 255;
3358  else if (G < 0)
3359  G = 0;
3360 
3361  B = Y14 + U5;
3362  if ((B >> 8) > 0)
3363  B = 255;
3364  else if (B < 0)
3365  B = 0;
3366 
3367  *rgb++ = (unsigned char)R;
3368  *rgb++ = (unsigned char)G;
3369  *rgb++ = (unsigned char)B;
3370 
3371  //---
3372  R = Y15 + V2;
3373  if ((R >> 8) > 0)
3374  R = 255;
3375  else if (R < 0)
3376  R = 0;
3377 
3378  G = Y15 + UV;
3379  if ((G >> 8) > 0)
3380  G = 255;
3381  else if (G < 0)
3382  G = 0;
3383 
3384  B = Y15 + U5;
3385  if ((B >> 8) > 0)
3386  B = 255;
3387  else if (B < 0)
3388  B = 0;
3389 
3390  *rgb++ = (unsigned char)R;
3391  *rgb++ = (unsigned char)G;
3392  *rgb++ = (unsigned char)B;
3393  rgb = rgb - 9 * width + 1;
3394  }
3395  yuv += 3 * width;
3396  rgb += 9 * width;
3397  }
3398 }
3399 
3407 void vpImageConvert::RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
3408 {
3409  unsigned char *pt_input = rgb;
3410  unsigned char *pt_end = rgb + 3 * size;
3411  unsigned char *pt_output = rgba;
3412 
3413  while (pt_input != pt_end) {
3414  *(pt_output++) = *(pt_input++); // R
3415  *(pt_output++) = *(pt_input++); // G
3416  *(pt_output++) = *(pt_input++); // B
3417  *(pt_output++) = vpRGBa::alpha_default; // A
3418  }
3419 }
3420 
3428 void vpImageConvert::RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
3429 {
3430  unsigned char *pt_input = rgba;
3431  unsigned char *pt_end = rgba + 4 * size;
3432  unsigned char *pt_output = rgb;
3433 
3434  while (pt_input != pt_end) {
3435  *(pt_output++) = *(pt_input++); // R
3436  *(pt_output++) = *(pt_input++); // G
3437  *(pt_output++) = *(pt_input++); // B
3438  pt_input++;
3439  }
3440 }
3447 void vpImageConvert::RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int size)
3448 {
3449  bool checkSSSE3 = vpCPUFeatures::checkSSSE3();
3450 #if !VISP_HAVE_SSSE3
3451  checkSSSE3 = false;
3452 #endif
3453 
3454  if (checkSSSE3) {
3455 #if VISP_HAVE_SSSE3
3456  unsigned int i = 0;
3457 
3458  if (size >= 16) {
3459  // Mask to select R component
3460  const __m128i mask_R1 = _mm_set_epi8(-1, -1, -1, -1, 15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1);
3461  const __m128i mask_R2 = _mm_set_epi8(5, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3462  const __m128i mask_R3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1);
3463  const __m128i mask_R4 = _mm_set_epi8(13, -1, 10, -1, 7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1);
3464 
3465  // Mask to select G component
3466  const __m128i mask_G1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 13, -1, 10, -1, 7, -1, 4, -1, 1, -1);
3467  const __m128i mask_G2 = _mm_set_epi8(6, -1, 3, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3468  const __m128i mask_G3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 12, -1, 9, -1);
3469  const __m128i mask_G4 = _mm_set_epi8(14, -1, 11, -1, 8, -1, 5, -1, 2, -1, -1, -1, -1, -1, -1, -1);
3470 
3471  // Mask to select B component
3472  const __m128i mask_B1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1, 5, -1, 2, -1);
3473  const __m128i mask_B2 = _mm_set_epi8(7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3474  const __m128i mask_B3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 10, -1);
3475  const __m128i mask_B4 = _mm_set_epi8(15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1, -1, -1, -1, -1);
3476 
3477  // Mask to select the gray component
3478  const __m128i mask_low1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1);
3479  const __m128i mask_low2 = _mm_set_epi8(15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1);
3480 
3481  // Coefficients RGB to Gray
3482  const __m128i coeff_R = _mm_set_epi16(13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933);
3483  const __m128i coeff_G = _mm_set_epi16((short int)46871, (short int)46871, (short int)46871, (short int)46871,
3484  (short int)46871, (short int)46871, (short int)46871, (short int)46871);
3485  const __m128i coeff_B = _mm_set_epi16(4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732);
3486 
3487  for (; i <= size - 16; i += 16) {
3488  // Process 16 color pixels
3489  const __m128i data1 = _mm_loadu_si128((const __m128i *)rgb);
3490  const __m128i data2 = _mm_loadu_si128((const __m128i *)(rgb + 16));
3491  const __m128i data3 = _mm_loadu_si128((const __m128i *)(rgb + 32));
3492 
3493  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3494  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3495  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3496 
3497  const __m128i grays_0_7 =
3498  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3499  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3500 
3501  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4));
3502  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4));
3503  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4));
3504 
3505  const __m128i grays_8_15 =
3506  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R),
3507  _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G), _mm_mulhi_epu16(blue_8_15, coeff_B)));
3508 
3509  _mm_storeu_si128((__m128i *)grey,
3510  _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1), _mm_shuffle_epi8(grays_8_15, mask_low2)));
3511 
3512  rgb += 48;
3513  grey += 16;
3514  }
3515  }
3516 
3517  for (; i < size; i++) {
3518  *grey = (unsigned char)(0.2126 * (*rgb) + 0.7152 * (*(rgb + 1)) + 0.0722 * (*(rgb + 2)));
3519 
3520  rgb += 3;
3521  ++grey;
3522  }
3523 #endif
3524  } else {
3525  unsigned char *pt_input = rgb;
3526  unsigned char *pt_end = rgb + size * 3;
3527  unsigned char *pt_output = grey;
3528 
3529  while (pt_input != pt_end) {
3530  *pt_output = (unsigned char)(0.2126 * (*pt_input) + 0.7152 * (*(pt_input + 1)) + 0.0722 * (*(pt_input + 2)));
3531  pt_input += 3;
3532  pt_output++;
3533  }
3534  }
3535 }
3543 void vpImageConvert::RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int size)
3544 {
3545  bool checkSSSE3 = vpCPUFeatures::checkSSSE3();
3546 #if !VISP_HAVE_SSSE3
3547  checkSSSE3 = false;
3548 #endif
3549 
3550  if (checkSSSE3) {
3551 #if VISP_HAVE_SSSE3
3552  unsigned int i = 0;
3553 
3554  if (size >= 16) {
3555  // Mask to select R component
3556  const __m128i mask_R1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 12, -1, 8, -1, 4, -1, 0, -1);
3557  const __m128i mask_R2 = _mm_set_epi8(12, -1, 8, -1, 4, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3558 
3559  // Mask to select G component
3560  const __m128i mask_G1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 9, -1, 5, -1, 1, -1);
3561  const __m128i mask_G2 = _mm_set_epi8(13, -1, 9, -1, 5, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3562 
3563  // Mask to select B component
3564  const __m128i mask_B1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 10, -1, 6, -1, 2, -1);
3565  const __m128i mask_B2 = _mm_set_epi8(14, -1, 10, -1, 6, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3566 
3567  // Mask to select the gray component
3568  const __m128i mask_low1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1);
3569  const __m128i mask_low2 = _mm_set_epi8(15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1);
3570 
3571  // Coefficients RGB to Gray
3572  const __m128i coeff_R = _mm_set_epi16(13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933);
3573  const __m128i coeff_G = _mm_set_epi16((short int)46871, (short int)46871, (short int)46871, (short int)46871,
3574  (short int)46871, (short int)46871, (short int)46871, (short int)46871);
3575  const __m128i coeff_B = _mm_set_epi16(4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732);
3576 
3577  for (; i <= size - 16; i += 16) {
3578  // Process 2*4 color pixels
3579  const __m128i data1 = _mm_loadu_si128((const __m128i *)rgba);
3580  const __m128i data2 = _mm_loadu_si128((const __m128i *)(rgba + 16));
3581 
3582  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3583  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3584  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3585 
3586  const __m128i grays_0_7 =
3587  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3588  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3589 
3590  // Process next 2*4 color pixels
3591  const __m128i data3 = _mm_loadu_si128((const __m128i *)(rgba + 32));
3592  const __m128i data4 = _mm_loadu_si128((const __m128i *)(rgba + 48));
3593 
3594  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data3, mask_R1), _mm_shuffle_epi8(data4, mask_R2));
3595  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data3, mask_G1), _mm_shuffle_epi8(data4, mask_G2));
3596  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data3, mask_B1), _mm_shuffle_epi8(data4, mask_B2));
3597 
3598  const __m128i grays_8_15 =
3599  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R),
3600  _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G), _mm_mulhi_epu16(blue_8_15, coeff_B)));
3601 
3602  _mm_storeu_si128((__m128i *)grey,
3603  _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1), _mm_shuffle_epi8(grays_8_15, mask_low2)));
3604 
3605  rgba += 64;
3606  grey += 16;
3607  }
3608  }
3609 
3610  for (; i < size; i++) {
3611  *grey = (unsigned char)(0.2126 * (*rgba) + 0.7152 * (*(rgba + 1)) + 0.0722 * (*(rgba + 2)));
3612 
3613  rgba += 4;
3614  ++grey;
3615  }
3616 #endif
3617  } else {
3618  unsigned char *pt_input = rgba;
3619  unsigned char *pt_end = rgba + size * 4;
3620  unsigned char *pt_output = grey;
3621 
3622  while (pt_input != pt_end) {
3623  *pt_output = (unsigned char)(0.2126 * (*pt_input) + 0.7152 * (*(pt_input + 1)) + 0.0722 * (*(pt_input + 2)));
3624  pt_input += 4;
3625  pt_output++;
3626  }
3627  }
3628 }
3629 
3635 void vpImageConvert::GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int size)
3636 {
3637  unsigned char *pt_input = grey;
3638  unsigned char *pt_end = grey + size;
3639  unsigned char *pt_output = rgba;
3640 
3641  while (pt_input != pt_end) {
3642  unsigned char p = *pt_input;
3643  *(pt_output) = p; // R
3644  *(pt_output + 1) = p; // G
3645  *(pt_output + 2) = p; // B
3646  *(pt_output + 3) = vpRGBa::alpha_default; // A
3647 
3648  pt_input++;
3649  pt_output += 4;
3650  }
3651 }
3652 
3657 void vpImageConvert::GreyToRGB(unsigned char *grey, unsigned char *rgb, unsigned int size)
3658 {
3659  unsigned char *pt_input = grey;
3660  unsigned char *pt_end = grey + size;
3661  unsigned char *pt_output = rgb;
3662 
3663  while (pt_input != pt_end) {
3664  unsigned char p = *pt_input;
3665  *(pt_output) = p; // R
3666  *(pt_output + 1) = p; // G
3667  *(pt_output + 2) = p; // B
3668 
3669  pt_input++;
3670  pt_output += 3;
3671  }
3672 }
3673 
3681 void vpImageConvert::BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height,
3682  bool flip)
3683 {
3684  // if we have to flip the image, we start from the end last scanline so the
3685  // step is negative
3686  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
3687 
3688  // starting source address = last line if we need to flip the image
3689  unsigned char *src = (flip) ? (bgr + (width * height * 3) + lineStep) : bgr;
3690 
3691  for (unsigned int i = 0; i < height; i++) {
3692  unsigned char *line = src;
3693  for (unsigned int j = 0; j < width; j++) {
3694  *rgba++ = *(line + 2);
3695  *rgba++ = *(line + 1);
3696  *rgba++ = *(line + 0);
3697  *rgba++ = vpRGBa::alpha_default;
3698 
3699  line += 3;
3700  }
3701  // go to the next line
3702  src += lineStep;
3703  }
3704 }
3705 
3711 void vpImageConvert::BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height,
3712  bool flip)
3713 {
3714  bool checkSSSE3 = vpCPUFeatures::checkSSSE3();
3715 #if !VISP_HAVE_SSSE3
3716  checkSSSE3 = false;
3717 #endif
3718 
3719  if (checkSSSE3) {
3720 #if VISP_HAVE_SSSE3
3721  // Mask to select B component
3722  const __m128i mask_B1 = _mm_set_epi8(-1, -1, -1, -1, 15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1);
3723  const __m128i mask_B2 = _mm_set_epi8(5, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3724  const __m128i mask_B3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1);
3725  const __m128i mask_B4 = _mm_set_epi8(13, -1, 10, -1, 7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1);
3726 
3727  // Mask to select G component
3728  const __m128i mask_G1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 13, -1, 10, -1, 7, -1, 4, -1, 1, -1);
3729  const __m128i mask_G2 = _mm_set_epi8(6, -1, 3, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3730  const __m128i mask_G3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 12, -1, 9, -1);
3731  const __m128i mask_G4 = _mm_set_epi8(14, -1, 11, -1, 8, -1, 5, -1, 2, -1, -1, -1, -1, -1, -1, -1);
3732 
3733  // Mask to select R component
3734  const __m128i mask_R1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1, 5, -1, 2, -1);
3735  const __m128i mask_R2 = _mm_set_epi8(7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3736  const __m128i mask_R3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 10, -1);
3737  const __m128i mask_R4 = _mm_set_epi8(15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1, -1, -1, -1, -1);
3738 
3739  // Mask to select the gray component
3740  const __m128i mask_low1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1);
3741  const __m128i mask_low2 = _mm_set_epi8(15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1);
3742 
3743  // Coefficients RGB to Gray
3744  // const __m128i coeff_R = _mm_set_epi8(
3745  // 54, -1, 54, -1, 54, -1, 54, -1, 54, -1, 54, -1, 54, -1, 54, -1
3746  // );
3747  // const __m128i coeff_G = _mm_set_epi8(
3748  // 183, -1, 183, -1, 183, -1, 183, -1, 183, -1, 183, -1, 183, -1,
3749  // 183, -1
3750  // );
3751  // const __m128i coeff_B = _mm_set_epi8(
3752  // 18, -1, 18, -1, 18, -1, 18, -1, 18, -1, 18, -1, 18, -1, 18, -1
3753  // );
3754  // const __m128i coeff_R = _mm_set_epi16(
3755  // 6969*2, 6969*2, 6969*2, 6969*2, 6969*2, 6969*2, 6969*2, 6969*2
3756  // );
3757  // const __m128i coeff_G = _mm_set_epi16(
3758  // 23434*2, 23434*2, 23434*2, 23434*2, 23434*2, 23434*2, 23434*2,
3759  // 23434*2
3760  // );
3761  // const __m128i coeff_B = _mm_set_epi16(
3762  // 2365*2, 2365*2, 2365*2, 2365*2, 2365*2, 2365*2, 2365*2, 2365*2
3763  // );
3764  const __m128i coeff_R = _mm_set_epi16(13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933);
3765  const __m128i coeff_G = _mm_set_epi16((short int)46871, (short int)46871, (short int)46871, (short int)46871,
3766  (short int)46871, (short int)46871, (short int)46871, (short int)46871);
3767  const __m128i coeff_B = _mm_set_epi16(4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732);
3768 
3769  if (flip) {
3770  int i = ((int)height) - 1;
3771  int lineStep = -(int)(width * 3);
3772  bgr = bgr + (width * (height - 1) * 3);
3773 
3774  unsigned char *linePtr = bgr;
3775  unsigned char r, g, b;
3776 
3777  if (width >= 16) {
3778  for (; i >= 0; i--) {
3779  unsigned int j = 0;
3780 
3781  for (; j <= width - 16; j += 16) {
3782  // Process 16 color pixels
3783  const __m128i data1 = _mm_loadu_si128((const __m128i *)bgr);
3784  const __m128i data2 = _mm_loadu_si128((const __m128i *)(bgr + 16));
3785  const __m128i data3 = _mm_loadu_si128((const __m128i *)(bgr + 32));
3786 
3787  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3788  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3789  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3790 
3791  const __m128i grays_0_7 =
3792  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3793  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3794 
3795  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4));
3796  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4));
3797  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4));
3798 
3799  const __m128i grays_8_15 =
3800  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R), _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G),
3801  _mm_mulhi_epu16(blue_8_15, coeff_B)));
3802 
3803  _mm_storeu_si128((__m128i *)grey, _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1),
3804  _mm_shuffle_epi8(grays_8_15, mask_low2)));
3805 
3806  bgr += 48;
3807  grey += 16;
3808  }
3809 
3810  for (; j < width; j++) {
3811  b = *(bgr++);
3812  g = *(bgr++);
3813  r = *(bgr++);
3814  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
3815  }
3816 
3817  linePtr += lineStep;
3818  bgr = linePtr;
3819  }
3820  }
3821 
3822  for (; i >= 0; i--) {
3823  for (unsigned int j = 0; j < width; j++) {
3824  b = *(bgr++);
3825  g = *(bgr++);
3826  r = *(bgr++);
3827  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
3828  }
3829 
3830  linePtr += lineStep;
3831  bgr = linePtr;
3832  }
3833  } else {
3834  unsigned int i = 0;
3835  unsigned int size = width * height;
3836 
3837  if (size >= 16) {
3838  for (; i <= size - 16; i += 16) {
3839  // Process 16 color pixels
3840  const __m128i data1 = _mm_loadu_si128((const __m128i *)bgr);
3841  const __m128i data2 = _mm_loadu_si128((const __m128i *)(bgr + 16));
3842  const __m128i data3 = _mm_loadu_si128((const __m128i *)(bgr + 32));
3843 
3844  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3845  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3846  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3847 
3848  const __m128i grays_0_7 =
3849  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3850  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3851 
3852  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4));
3853  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4));
3854  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4));
3855 
3856  const __m128i grays_8_15 =
3857  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R),
3858  _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G), _mm_mulhi_epu16(blue_8_15, coeff_B)));
3859 
3860  _mm_storeu_si128((__m128i *)grey, _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1),
3861  _mm_shuffle_epi8(grays_8_15, mask_low2)));
3862 
3863  bgr += 48;
3864  grey += 16;
3865  }
3866  }
3867 
3868  for (; i < size; i++) {
3869  *grey = (unsigned char)(0.2126 * (*(bgr + 2)) + 0.7152 * (*(bgr + 1)) + 0.0722 * (*bgr));
3870 
3871  bgr += 3;
3872  ++grey;
3873  }
3874  }
3875 #endif
3876  } else {
3877  // if we have to flip the image, we start from the end last scanline so
3878  // the step is negative
3879  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
3880 
3881  // starting source address = last line if we need to flip the image
3882  unsigned char *src = (flip) ? bgr + (width * height * 3) + lineStep : bgr;
3883 
3884  for (unsigned int i = 0; i < height; i++) {
3885  unsigned char *line = src;
3886  for (unsigned int j = 0; j < width; j++) {
3887  *grey++ = (unsigned char)(0.2126 * *(line + 2) + 0.7152 * *(line + 1) + 0.0722 * *(line + 0));
3888  line += 3;
3889  }
3890 
3891  // go to the next line
3892  src += lineStep;
3893  }
3894  }
3895 }
3896 
3904 void vpImageConvert::RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int width, unsigned int height,
3905  bool flip)
3906 {
3907  // if we have to flip the image, we start from the end last scanline so the
3908  // step is negative
3909  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
3910 
3911  // starting source address = last line if we need to flip the image
3912  unsigned char *src = (flip) ? (rgb + (width * height * 3) + lineStep) : rgb;
3913 
3914  unsigned int j = 0;
3915  unsigned int i = 0;
3916 
3917  for (i = 0; i < height; i++) {
3918  unsigned char *line = src;
3919  for (j = 0; j < width; j++) {
3920  *rgba++ = *(line++);
3921  *rgba++ = *(line++);
3922  *rgba++ = *(line++);
3923  *rgba++ = vpRGBa::alpha_default;
3924  }
3925  // go to the next line
3926  src += lineStep;
3927  }
3928 }
3929 
3935 void vpImageConvert::RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height,
3936  bool flip)
3937 {
3938  if (flip) {
3939  bool checkSSSE3 = vpCPUFeatures::checkSSSE3();
3940 #if !VISP_HAVE_SSSE3
3941  checkSSSE3 = false;
3942 #endif
3943 
3944  if (checkSSSE3) {
3945 #if VISP_HAVE_SSSE3
3946  int i = ((int)height) - 1;
3947  int lineStep = -(int)(width * 3);
3948  rgb = rgb + (width * (height - 1) * 3);
3949 
3950  unsigned char *linePtr = rgb;
3951  unsigned char r, g, b;
3952 
3953  if (width >= 16) {
3954  // Mask to select R component
3955  const __m128i mask_R1 = _mm_set_epi8(-1, -1, -1, -1, 15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1);
3956  const __m128i mask_R2 = _mm_set_epi8(5, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3957  const __m128i mask_R3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1);
3958  const __m128i mask_R4 = _mm_set_epi8(13, -1, 10, -1, 7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1);
3959 
3960  // Mask to select G component
3961  const __m128i mask_G1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 13, -1, 10, -1, 7, -1, 4, -1, 1, -1);
3962  const __m128i mask_G2 = _mm_set_epi8(6, -1, 3, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3963  const __m128i mask_G3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 12, -1, 9, -1);
3964  const __m128i mask_G4 = _mm_set_epi8(14, -1, 11, -1, 8, -1, 5, -1, 2, -1, -1, -1, -1, -1, -1, -1);
3965 
3966  // Mask to select B component
3967  const __m128i mask_B1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1, 5, -1, 2, -1);
3968  const __m128i mask_B2 = _mm_set_epi8(7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3969  const __m128i mask_B3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 10, -1);
3970  const __m128i mask_B4 = _mm_set_epi8(15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1, -1, -1, -1, -1);
3971 
3972  // Mask to select the gray component
3973  const __m128i mask_low1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1);
3974  const __m128i mask_low2 = _mm_set_epi8(15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1);
3975 
3976  // Coefficients RGB to Gray
3977  const __m128i coeff_R = _mm_set_epi16(13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933);
3978  const __m128i coeff_G = _mm_set_epi16((short int)46871, (short int)46871, (short int)46871, (short int)46871,
3979  (short int)46871, (short int)46871, (short int)46871, (short int)46871);
3980  const __m128i coeff_B = _mm_set_epi16(4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732);
3981 
3982  for (; i >= 0; i--) {
3983  unsigned int j = 0;
3984 
3985  for (; j <= width - 16; j += 16) {
3986  // Process 16 color pixels
3987  const __m128i data1 = _mm_loadu_si128((const __m128i *)rgb);
3988  const __m128i data2 = _mm_loadu_si128((const __m128i *)(rgb + 16));
3989  const __m128i data3 = _mm_loadu_si128((const __m128i *)(rgb + 32));
3990 
3991  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3992  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3993  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3994 
3995  const __m128i grays_0_7 =
3996  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3997  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3998 
3999  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4));
4000  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4));
4001  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4));
4002 
4003  const __m128i grays_8_15 =
4004  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R), _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G),
4005  _mm_mulhi_epu16(blue_8_15, coeff_B)));
4006 
4007  _mm_storeu_si128((__m128i *)grey, _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1),
4008  _mm_shuffle_epi8(grays_8_15, mask_low2)));
4009 
4010  rgb += 48;
4011  grey += 16;
4012  }
4013 
4014  for (; j < width; j++) {
4015  r = *(rgb++);
4016  g = *(rgb++);
4017  b = *(rgb++);
4018  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
4019  }
4020 
4021  linePtr += lineStep;
4022  rgb = linePtr;
4023  }
4024  }
4025 
4026  for (; i >= 0; i--) {
4027  for (unsigned int j = 0; j < width; j++) {
4028  r = *(rgb++);
4029  g = *(rgb++);
4030  b = *(rgb++);
4031  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
4032  }
4033 
4034  linePtr += lineStep;
4035  rgb = linePtr;
4036  }
4037 #endif
4038  } else {
4039  // if we have to flip the image, we start from the end last scanline so
4040  // the step is negative
4041  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
4042 
4043  // starting source address = last line if we need to flip the image
4044  unsigned char *src = (flip) ? rgb + (width * height * 3) + lineStep : rgb;
4045 
4046  unsigned int j = 0;
4047  unsigned int i = 0;
4048 
4049  unsigned r, g, b;
4050 
4051  for (i = 0; i < height; i++) {
4052  unsigned char *line = src;
4053  for (j = 0; j < width; j++) {
4054  r = *(line++);
4055  g = *(line++);
4056  b = *(line++);
4057  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
4058  }
4059 
4060  // go to the next line
4061  src += lineStep;
4062  }
4063  }
4064  } else {
4065  RGBToGrey(rgb, grey, width * height);
4066  }
4067 }
4068 
4072 void vpImageConvert::computeYCbCrLUT()
4073 {
4074  if (YCbCrLUTcomputed == false) {
4075  int index = 256;
4076 
4077  while (index--) {
4078 
4079  int aux = index - 128;
4080  vpImageConvert::vpCrr[index] = (int)(364.6610 * aux) >> 8;
4081  vpImageConvert::vpCgb[index] = (int)(-89.8779 * aux) >> 8;
4082  vpImageConvert::vpCgr[index] = (int)(-185.8154 * aux) >> 8;
4083  vpImageConvert::vpCbb[index] = (int)(460.5724 * aux) >> 8;
4084  }
4085 
4086  YCbCrLUTcomputed = true;
4087  }
4088 }
4089 
4109 void vpImageConvert::YCbCrToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
4110 {
4111  unsigned char *cbv;
4112  unsigned char *crv;
4113  unsigned char *pt_ycbcr = ycbcr;
4114  unsigned char *pt_rgb = rgb;
4115  cbv = pt_ycbcr + 1;
4116  crv = pt_ycbcr + 3;
4117 
4118  vpImageConvert::computeYCbCrLUT();
4119 
4120  int col = 0;
4121 
4122  while (size--) {
4123  int val_r, val_g, val_b;
4124  if (!(col++ % 2)) {
4125  cbv = pt_ycbcr + 1;
4126  crv = pt_ycbcr + 3;
4127  }
4128 
4129  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4130  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4131  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4132 
4133  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4134 
4135  *pt_rgb++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4136  *pt_rgb++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4137  *pt_rgb++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4138 
4139  pt_ycbcr += 2;
4140  }
4141 }
4142 
4166 void vpImageConvert::YCbCrToRGBa(unsigned char *ycbcr, unsigned char *rgba, unsigned int size)
4167 {
4168  unsigned char *cbv;
4169  unsigned char *crv;
4170  unsigned char *pt_ycbcr = ycbcr;
4171  unsigned char *pt_rgba = rgba;
4172  cbv = pt_ycbcr + 1;
4173  crv = pt_ycbcr + 3;
4174 
4175  vpImageConvert::computeYCbCrLUT();
4176 
4177  int col = 0;
4178 
4179  while (size--) {
4180  int val_r, val_g, val_b;
4181  if (!(col++ % 2)) {
4182  cbv = pt_ycbcr + 1;
4183  crv = pt_ycbcr + 3;
4184  }
4185 
4186  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4187  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4188  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4189 
4190  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4191 
4192  *pt_rgba++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4193  *pt_rgba++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4194  *pt_rgba++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4195  *pt_rgba++ = vpRGBa::alpha_default;
4196 
4197  pt_ycbcr += 2;
4198  }
4199 }
4200 
4217 void vpImageConvert::YCbCrToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
4218 {
4219  unsigned int i = 0, j = 0;
4220 
4221  while (j < size * 2) {
4222  grey[i++] = yuv[j];
4223  grey[i++] = yuv[j + 2];
4224  j += 4;
4225  }
4226 }
4227 
4246 void vpImageConvert::YCrCbToRGB(unsigned char *ycrcb, unsigned char *rgb, unsigned int size)
4247 {
4248  unsigned char *cbv;
4249  unsigned char *crv;
4250  unsigned char *pt_ycbcr = ycrcb;
4251  unsigned char *pt_rgb = rgb;
4252  crv = pt_ycbcr + 1;
4253  cbv = pt_ycbcr + 3;
4254 
4255  vpImageConvert::computeYCbCrLUT();
4256 
4257  int col = 0;
4258 
4259  while (size--) {
4260  int val_r, val_g, val_b;
4261  if (!(col++ % 2)) {
4262  crv = pt_ycbcr + 1;
4263  cbv = pt_ycbcr + 3;
4264  }
4265 
4266  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4267  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4268  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4269 
4270  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4271 
4272  *pt_rgb++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4273  *pt_rgb++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4274  *pt_rgb++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4275 
4276  pt_ycbcr += 2;
4277  }
4278 }
4301 void vpImageConvert::YCrCbToRGBa(unsigned char *ycrcb, unsigned char *rgba, unsigned int size)
4302 {
4303  unsigned char *cbv;
4304  unsigned char *crv;
4305  unsigned char *pt_ycbcr = ycrcb;
4306  unsigned char *pt_rgba = rgba;
4307  crv = pt_ycbcr + 1;
4308  cbv = pt_ycbcr + 3;
4309 
4310  vpImageConvert::computeYCbCrLUT();
4311 
4312  int col = 0;
4313 
4314  while (size--) {
4315  int val_r, val_g, val_b;
4316  if (!(col++ % 2)) {
4317  crv = pt_ycbcr + 1;
4318  cbv = pt_ycbcr + 3;
4319  }
4320 
4321  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4322  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4323  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4324 
4325  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4326 
4327  *pt_rgba++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4328  *pt_rgba++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4329  *pt_rgba++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4330  *pt_rgba++ = vpRGBa::alpha_default;
4331 
4332  pt_ycbcr += 2;
4333  }
4334 }
4335 
4373 {
4374  size_t n = src.getNumberOfPixel();
4375  unsigned int height = src.getHeight();
4376  unsigned int width = src.getWidth();
4377  unsigned char *input;
4378  unsigned char *dst;
4379 
4380  vpImage<unsigned char> *tabChannel[4];
4381 
4382  /* incrsrc[0] = 0; //init
4383  incrsrc[1] = 0; //step after the first used channel
4384  incrsrc[2] = 0; //step after the second used channel
4385  incrsrc[3] = 0;
4386  incrsrc[4] = 0;
4387  */
4388  tabChannel[0] = pR;
4389  tabChannel[1] = pG;
4390  tabChannel[2] = pB;
4391  tabChannel[3] = pa;
4392 
4393  size_t i; /* ordre */
4394  for (unsigned int j = 0; j < 4; j++) {
4395  if (tabChannel[j] != NULL) {
4396  if (tabChannel[j]->getHeight() != height || tabChannel[j]->getWidth() != width) {
4397  tabChannel[j]->resize(height, width);
4398  }
4399  dst = (unsigned char *)tabChannel[j]->bitmap;
4400 
4401  input = (unsigned char *)src.bitmap + j;
4402  i = 0;
4403 #if 1 // optimization
4404  if (n >= 4) { /* boucle deroulee lsize fois */
4405  n -= 3;
4406  for (; i < n; i += 4) {
4407  *dst = *input;
4408  input += 4;
4409  dst++;
4410  *dst = *input;
4411  input += 4;
4412  dst++;
4413  *dst = *input;
4414  input += 4;
4415  dst++;
4416  *dst = *input;
4417  input += 4;
4418  dst++;
4419  }
4420  n += 3;
4421  }
4422 #endif
4423  for (; i < n; i++) {
4424  *dst = *input;
4425  input += 4;
4426  dst++;
4427  }
4428  }
4429  }
4430 }
4431 
4442 {
4443  // Check if the input channels have all the same dimensions
4444  std::map<unsigned int, unsigned int> mapOfWidths, mapOfHeights;
4445  if (R != NULL) {
4446  mapOfWidths[R->getWidth()]++;
4447  mapOfHeights[R->getHeight()]++;
4448  }
4449 
4450  if (G != NULL) {
4451  mapOfWidths[G->getWidth()]++;
4452  mapOfHeights[G->getHeight()]++;
4453  }
4454 
4455  if (B != NULL) {
4456  mapOfWidths[B->getWidth()]++;
4457  mapOfHeights[B->getHeight()]++;
4458  }
4459 
4460  if (a != NULL) {
4461  mapOfWidths[a->getWidth()]++;
4462  mapOfHeights[a->getHeight()]++;
4463  }
4464 
4465  if (mapOfWidths.size() == 1 && mapOfHeights.size() == 1) {
4466  unsigned int width = mapOfWidths.begin()->first;
4467  unsigned int height = mapOfHeights.begin()->first;
4468 
4469  RGBa.resize(height, width);
4470 
4471  unsigned int size = width * height;
4472  for (unsigned int i = 0; i < size; i++) {
4473  if (R != NULL) {
4474  RGBa.bitmap[i].R = R->bitmap[i];
4475  }
4476 
4477  if (G != NULL) {
4478  RGBa.bitmap[i].G = G->bitmap[i];
4479  }
4480 
4481  if (B != NULL) {
4482  RGBa.bitmap[i].B = B->bitmap[i];
4483  }
4484 
4485  if (a != NULL) {
4486  RGBa.bitmap[i].A = a->bitmap[i];
4487  }
4488  }
4489  } else {
4490  throw vpException(vpException::dimensionError, "Mismatch dimensions !");
4491  }
4492 }
4493 
4504 void vpImageConvert::MONO16ToGrey(unsigned char *grey16, unsigned char *grey, unsigned int size)
4505 {
4506  int i = (((int)size) << 1) - 1;
4507  int j = (int)size - 1;
4508 
4509  while (i >= 0) {
4510  int y = grey16[i--];
4511  grey[j--] = static_cast<unsigned char>((y + (grey16[i--] << 8)) >> 8);
4512  }
4513 }
4514 
4527 void vpImageConvert::MONO16ToRGBa(unsigned char *grey16, unsigned char *rgba, unsigned int size)
4528 {
4529  int i = (((int)size) << 1) - 1;
4530  int j = (int)(size * 4 - 1);
4531 
4532  while (i >= 0) {
4533  int y = grey16[i--];
4534  unsigned char v = static_cast<unsigned char>((y + (grey16[i--] << 8)) >> 8);
4535  rgba[j--] = vpRGBa::alpha_default;
4536  rgba[j--] = v;
4537  rgba[j--] = v;
4538  rgba[j--] = v;
4539  }
4540 }
4541 
4542 void vpImageConvert::HSV2RGB(const double *hue_, const double *saturation_, const double *value_, unsigned char *rgb,
4543  const unsigned int size, const unsigned int step)
4544 {
4545  for (unsigned int i = 0; i < size; i++) {
4546  double hue = hue_[i], saturation = saturation_[i], value = value_[i];
4547 
4548  if (vpMath::equal(saturation, 0.0, std::numeric_limits<double>::epsilon())) {
4549  hue = value;
4550  saturation = value;
4551  } else {
4552  double h = hue * 6.0;
4553  double s = saturation;
4554  double v = value;
4555 
4556  if (vpMath::equal(h, 6.0, std::numeric_limits<double>::epsilon())) {
4557  h = 0.0;
4558  }
4559 
4560  double f = h - (int)h;
4561  double p = v * (1.0 - s);
4562  double q = v * (1.0 - s * f);
4563  double t = v * (1.0 - s * (1.0 - f));
4564 
4565  switch ((int)h) {
4566  case 0:
4567  hue = v;
4568  saturation = t;
4569  value = p;
4570  break;
4571 
4572  case 1:
4573  hue = q;
4574  saturation = v;
4575  value = p;
4576  break;
4577 
4578  case 2:
4579  hue = p;
4580  saturation = v;
4581  value = t;
4582  break;
4583 
4584  case 3:
4585  hue = p;
4586  saturation = q;
4587  value = v;
4588  break;
4589 
4590  case 4:
4591  hue = t;
4592  saturation = p;
4593  value = v;
4594  break;
4595 
4596  default: // case 5:
4597  hue = v;
4598  saturation = p;
4599  value = q;
4600  break;
4601  }
4602  }
4603 
4604  rgb[i * step] = (unsigned char)vpMath::round(hue * 255.0);
4605  rgb[i * step + 1] = (unsigned char)vpMath::round(saturation * 255.0);
4606  rgb[i * step + 2] = (unsigned char)vpMath::round(value * 255.0);
4607  if (step == 4) // alpha
4608  rgb[i * step + 3] = vpRGBa::alpha_default;
4609  }
4610 }
4611 
4612 void vpImageConvert::RGB2HSV(const unsigned char *rgb, double *hue, double *saturation, double *value,
4613  const unsigned int size, const unsigned int step)
4614 {
4615  for (unsigned int i = 0; i < size; i++) {
4616  double red, green, blue;
4617  double h, s, v;
4618  double min, max;
4619 
4620  red = rgb[i * step] / 255.0;
4621  green = rgb[i * step + 1] / 255.0;
4622  blue = rgb[i * step + 2] / 255.0;
4623 
4624  if (red > green) {
4625  max = ((std::max))(red, blue);
4626  min = ((std::min))(green, blue);
4627  } else {
4628  max = ((std::max))(green, blue);
4629  min = ((std::min))(red, blue);
4630  }
4631 
4632  v = max;
4633 
4634  if (!vpMath::equal(max, 0.0, std::numeric_limits<double>::epsilon())) {
4635  s = (max - min) / max;
4636  } else {
4637  s = 0.0;
4638  }
4639 
4640  if (vpMath::equal(s, 0.0, std::numeric_limits<double>::epsilon())) {
4641  h = 0.0;
4642  } else {
4643  double delta = max - min;
4644  if (vpMath::equal(delta, 0.0, std::numeric_limits<double>::epsilon())) {
4645  delta = 1.0;
4646  }
4647 
4648  if (vpMath::equal(red, max, std::numeric_limits<double>::epsilon())) {
4649  h = (green - blue) / delta;
4650  } else if (vpMath::equal(green, max, std::numeric_limits<double>::epsilon())) {
4651  h = 2 + (blue - red) / delta;
4652  } else {
4653  h = 4 + (red - green) / delta;
4654  }
4655 
4656  h /= 6.0;
4657  if (h < 0.0) {
4658  h += 1.0;
4659  } else if (h > 1.0) {
4660  h -= 1.0;
4661  }
4662  }
4663 
4664  hue[i] = h;
4665  saturation[i] = s;
4666  value[i] = v;
4667  }
4668 }
4669 
4682 void vpImageConvert::HSVToRGBa(const double *hue, const double *saturation, const double *value, unsigned char *rgba,
4683  const unsigned int size)
4684 {
4685  vpImageConvert::HSV2RGB(hue, saturation, value, rgba, size, 4);
4686 }
4687 
4700 void vpImageConvert::HSVToRGBa(const unsigned char *hue, const unsigned char *saturation, const unsigned char *value,
4701  unsigned char *rgba, const unsigned int size)
4702 {
4703  for (unsigned int i = 0; i < size; i++) {
4704  double h = hue[i] / 255.0, s = saturation[i] / 255.0, v = value[i] / 255.0;
4705 
4706  vpImageConvert::HSVToRGBa(&h, &s, &v, (rgba + i * 4), 1);
4707  }
4708 }
4709 
4721 void vpImageConvert::RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value,
4722  const unsigned int size)
4723 {
4724  vpImageConvert::RGB2HSV(rgba, hue, saturation, value, size, 4);
4725 }
4726 
4738 void vpImageConvert::RGBaToHSV(const unsigned char *rgba, unsigned char *hue, unsigned char *saturation,
4739  unsigned char *value, const unsigned int size)
4740 {
4741  for (unsigned int i = 0; i < size; i++) {
4742  double h, s, v;
4743  vpImageConvert::RGBaToHSV((rgba + i * 4), &h, &s, &v, 1);
4744 
4745  hue[i] = (unsigned char)(255.0 * h);
4746  saturation[i] = (unsigned char)(255.0 * s);
4747  value[i] = (unsigned char)(255.0 * v);
4748  }
4749 }
4750 
4760 void vpImageConvert::HSVToRGB(const double *hue, const double *saturation, const double *value, unsigned char *rgb,
4761  const unsigned int size)
4762 {
4763  vpImageConvert::HSV2RGB(hue, saturation, value, rgb, size, 3);
4764 }
4765 
4775 void vpImageConvert::HSVToRGB(const unsigned char *hue, const unsigned char *saturation, const unsigned char *value,
4776  unsigned char *rgb, const unsigned int size)
4777 {
4778  for (unsigned int i = 0; i < size; i++) {
4779  double h = hue[i] / 255.0, s = saturation[i] / 255.0, v = value[i] / 255.0;
4780 
4781  vpImageConvert::HSVToRGB(&h, &s, &v, (rgb + i * 3), 1);
4782  }
4783 }
4784 
4795 void vpImageConvert::RGBToHSV(const unsigned char *rgb, double *hue, double *saturation, double *value,
4796  const unsigned int size)
4797 {
4798  vpImageConvert::RGB2HSV(rgb, hue, saturation, value, size, 3);
4799 }
4800 
4811 void vpImageConvert::RGBToHSV(const unsigned char *rgb, unsigned char *hue, unsigned char *saturation,
4812  unsigned char *value, const unsigned int size)
4813 {
4814  for (unsigned int i = 0; i < size; i++) {
4815  double h, s, v;
4816 
4817  vpImageConvert::RGBToHSV((rgb + i * 3), &h, &s, &v, 1);
4818 
4819  hue[i] = (unsigned char)(255.0 * h);
4820  saturation[i] = (unsigned char)(255.0 * s);
4821  value[i] = (unsigned char)(255.0 * v);
4822  }
4823 }
unsigned int getCols() const
Definition: vpImage.h:169
static void BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static void YUYVToRGBa(unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height)
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int size)
unsigned int getWidth() const
Definition: vpImage.h:239
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
void getMinMaxValue(Type &min, Type &max) const
Look for the minimum and the maximum value within the bitmap.
Definition: vpImage.h:1000
static void RGBToHSV(const unsigned char *rgb, double *hue, double *saturation, double *value, const unsigned int size)
unsigned char B
Blue component.
Definition: vpRGBa.h:150
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false)
Type * bitmap
points toward the bitmap
Definition: vpImage.h:133
static void MONO16ToGrey(unsigned char *grey16, unsigned char *grey, unsigned int size)
static bool equal(double x, double y, double s=0.001)
Definition: vpMath.h:290
static void YUV422ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
static void YUV420ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int size)
error that can be emited by ViSP classes.
Definition: vpException.h:71
static void YUV422ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
static void YCbCrToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void YUV411ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
static void split(const vpImage< vpRGBa > &src, vpImage< unsigned char > *pR, vpImage< unsigned char > *pG, vpImage< unsigned char > *pB, vpImage< unsigned char > *pa=NULL)
static void YUVToRGB(unsigned char y, unsigned char u, unsigned char v, unsigned char &r, unsigned char &g, unsigned char &b)
unsigned char G
Green component.
Definition: vpRGBa.h:149
static void GreyToRGB(unsigned char *grey, unsigned char *rgb, unsigned int size)
static int round(const double x)
Definition: vpMath.h:235
Definition: vpRGBa.h:66
static void YUV444ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
static void YUV420ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YVU9ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YUV422ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
unsigned int getRows() const
Definition: vpImage.h:211
static void YVU9ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
static void YV12ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
unsigned int getSize() const
Definition: vpImage.h:219
static void YCbCrToGrey(unsigned char *ycbcr, unsigned char *grey, unsigned int size)
unsigned char A
Additionnal component.
Definition: vpRGBa.h:151
static void YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
static void MONO16ToRGBa(unsigned char *grey16, unsigned char *rgba, unsigned int size)
unsigned int getNumberOfPixel() const
Definition: vpImage.h:201
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:866
VISP_EXPORT bool checkSSSE3()
static void merge(const vpImage< unsigned char > *R, const vpImage< unsigned char > *G, const vpImage< unsigned char > *B, const vpImage< unsigned char > *a, vpImage< vpRGBa > &RGBa)
static void RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value, const unsigned int size)
static void YUYVToRGB(unsigned char *yuyv, unsigned char *rgb, unsigned int width, unsigned int height)
static void YUV444ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
static void YUV444ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void YUV411ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
unsigned char R
Red component.
Definition: vpRGBa.h:148
static void HSVToRGBa(const double *hue, const double *saturation, const double *value, unsigned char *rgba, const unsigned int size)
#define vpDEBUG_TRACE
Definition: vpDebug.h:487
unsigned int getHeight() const
Definition: vpImage.h:178
static void YCbCrToRGBa(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void YUV411ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
static void YCrCbToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void HSVToRGB(const double *hue, const double *saturation, const double *value, unsigned char *rgb, const unsigned int size)
static void YCrCbToRGBa(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int size)
static void createDepthHistogram(const vpImage< uint16_t > &src_depth, vpImage< vpRGBa > &dest_rgba)
static void YV12ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
static void YUV420ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)