Visual Servoing Platform  version 3.2.1 under development (2019-07-16)
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 
885 void vpImageConvert::convert(const vpImage<vpRGBa> &src, cv::Mat &dest)
886 {
887  cv::Mat vpToMat((int)src.getRows(), (int)src.getCols(), CV_8UC4, (void *)src.bitmap);
888  cv::cvtColor(vpToMat, dest, cv::COLOR_RGBA2BGR);
889 }
890 
929 void vpImageConvert::convert(const vpImage<unsigned char> &src, cv::Mat &dest, const bool copyData)
930 {
931  if (copyData) {
932  cv::Mat tmpMap((int)src.getRows(), (int)src.getCols(), CV_8UC1, (void *)src.bitmap);
933  dest = tmpMap.clone();
934  } else {
935  dest = cv::Mat((int)src.getRows(), (int)src.getCols(), CV_8UC1, (void *)src.bitmap);
936  }
937 }
938 
939 #endif
940 #endif
941 
942 #ifdef VISP_HAVE_YARP
943 
978 void vpImageConvert::convert(const vpImage<unsigned char> &src, yarp::sig::ImageOf<yarp::sig::PixelMono> *dest,
979  const bool copyData)
980 {
981  if (copyData) {
982  dest->resize(src.getWidth(), src.getHeight());
983  memcpy(dest->getRawImage(), src.bitmap, src.getHeight() * src.getWidth());
984  } else
985  dest->setExternal(src.bitmap, (int)src.getCols(), (int)src.getRows());
986 }
987 
1027 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelMono> *src, vpImage<unsigned char> &dest,
1028  const bool copyData)
1029 {
1030  dest.resize(src->height(), src->width());
1031  if (copyData)
1032  memcpy(dest.bitmap, src->getRawImage(), src->height() * src->width() * sizeof(yarp::sig::PixelMono));
1033  else
1034  dest.bitmap = src->getRawImage();
1035 }
1036 
1072 void vpImageConvert::convert(const vpImage<vpRGBa> &src, yarp::sig::ImageOf<yarp::sig::PixelRgba> *dest,
1073  const bool copyData)
1074 {
1075  if (copyData) {
1076  dest->resize(src.getWidth(), src.getHeight());
1077  memcpy(dest->getRawImage(), src.bitmap, src.getHeight() * src.getWidth() * sizeof(vpRGBa));
1078  } else
1079  dest->setExternal(src.bitmap, (int)src.getCols(), (int)src.getRows());
1080 }
1081 
1121 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelRgba> *src, vpImage<vpRGBa> &dest,
1122  const bool copyData)
1123 {
1124  dest.resize(src->height(), src->width());
1125  if (copyData)
1126  memcpy(dest.bitmap, src->getRawImage(), src->height() * src->width() * sizeof(yarp::sig::PixelRgba));
1127  else
1128  dest.bitmap = static_cast<vpRGBa *>(src->getRawImage());
1129 }
1130 
1164 void vpImageConvert::convert(const vpImage<vpRGBa> &src, yarp::sig::ImageOf<yarp::sig::PixelRgb> *dest)
1165 {
1166  dest->resize(src.getWidth(), src.getHeight());
1167  for (unsigned int i = 0; i < src.getRows(); i++) {
1168  for (unsigned int j = 0; j < src.getWidth(); j++) {
1169  dest->pixel(j, i).r = src[i][j].R;
1170  dest->pixel(j, i).g = src[i][j].G;
1171  dest->pixel(j, i).b = src[i][j].B;
1172  }
1173  }
1174 }
1175 
1215 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelRgb> *src, vpImage<vpRGBa> &dest)
1216 {
1217  dest.resize(src->height(), src->width());
1218  for (int i = 0; i < src->height(); i++) {
1219  for (int j = 0; j < src->width(); j++) {
1220  dest[i][j].R = src->pixel(j, i).r;
1221  dest[i][j].G = src->pixel(j, i).g;
1222  dest[i][j].B = src->pixel(j, i).b;
1223  dest[i][j].A = vpRGBa::alpha_default;
1224  }
1225  }
1226 }
1227 
1228 #endif
1229 
1230 #define vpSAT(c) \
1231  if (c & (~255)) { \
1232  if (c < 0) \
1233  c = 0; \
1234  else \
1235  c = 255; \
1236  }
1237 
1245 void vpImageConvert::YUYVToRGBa(unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height)
1246 {
1247  unsigned char *s;
1248  unsigned char *d;
1249  int w, h;
1250  int r, g, b, cr, cg, cb, y1, y2;
1251 
1252  h = (int)height;
1253  w = (int)width;
1254  s = yuyv;
1255  d = rgba;
1256  while (h--) {
1257  int c = w >> 1;
1258  while (c--) {
1259  y1 = *s++;
1260  cb = ((*s - 128) * 454) >> 8;
1261  cg = (*s++ - 128) * 88;
1262  y2 = *s++;
1263  cr = ((*s - 128) * 359) >> 8;
1264  cg = (cg + (*s++ - 128) * 183) >> 8;
1265 
1266  r = y1 + cr;
1267  b = y1 + cb;
1268  g = y1 - cg;
1269  vpSAT(r);
1270  vpSAT(g);
1271  vpSAT(b);
1272 
1273  *d++ = static_cast<unsigned char>(r);
1274  *d++ = static_cast<unsigned char>(g);
1275  *d++ = static_cast<unsigned char>(b);
1276  *d++ = vpRGBa::alpha_default;
1277 
1278  r = y2 + cr;
1279  b = y2 + cb;
1280  g = y2 - cg;
1281  vpSAT(r);
1282  vpSAT(g);
1283  vpSAT(b);
1284 
1285  *d++ = static_cast<unsigned char>(r);
1286  *d++ = static_cast<unsigned char>(g);
1287  *d++ = static_cast<unsigned char>(b);
1288  *d++ = vpRGBa::alpha_default;
1289  }
1290  }
1291 }
1292 
1300 void vpImageConvert::YUYVToRGB(unsigned char *yuyv, unsigned char *rgb, unsigned int width, unsigned int height)
1301 {
1302  unsigned char *s;
1303  unsigned char *d;
1304  int h, w;
1305  int r, g, b, cr, cg, cb, y1, y2;
1306 
1307  h = (int)height;
1308  w = (int)width;
1309  s = yuyv;
1310  d = rgb;
1311  while (h--) {
1312  int c = w >> 1;
1313  while (c--) {
1314  y1 = *s++;
1315  cb = ((*s - 128) * 454) >> 8;
1316  cg = (*s++ - 128) * 88;
1317  y2 = *s++;
1318  cr = ((*s - 128) * 359) >> 8;
1319  cg = (cg + (*s++ - 128) * 183) >> 8;
1320 
1321  r = y1 + cr;
1322  b = y1 + cb;
1323  g = y1 - cg;
1324  vpSAT(r);
1325  vpSAT(g);
1326  vpSAT(b);
1327 
1328  *d++ = static_cast<unsigned char>(r);
1329  *d++ = static_cast<unsigned char>(g);
1330  *d++ = static_cast<unsigned char>(b);
1331 
1332  r = y2 + cr;
1333  b = y2 + cb;
1334  g = y2 - cg;
1335  vpSAT(r);
1336  vpSAT(g);
1337  vpSAT(b);
1338 
1339  *d++ = static_cast<unsigned char>(r);
1340  *d++ = static_cast<unsigned char>(g);
1341  *d++ = static_cast<unsigned char>(b);
1342  }
1343  }
1344 }
1352 void vpImageConvert::YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
1353 {
1354  unsigned int i = 0, j = 0;
1355 
1356  while (j < size * 2) {
1357  grey[i++] = yuyv[j];
1358  grey[i++] = yuyv[j + 2];
1359  j += 4;
1360  }
1361 }
1362 
1369 void vpImageConvert::YUV411ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
1370 {
1371 #if 1
1372  // std::cout << "call optimized ConvertYUV411ToRGBa()" << std::endl;
1373  for (unsigned int i = size / 4; i; i--) {
1374  int U = (int)((*yuv++ - 128) * 0.354);
1375  int U5 = 5 * U;
1376  int Y0 = *yuv++;
1377  int Y1 = *yuv++;
1378  int V = (int)((*yuv++ - 128) * 0.707);
1379  int V2 = 2 * V;
1380  int Y2 = *yuv++;
1381  int Y3 = *yuv++;
1382  int UV = -U - V;
1383 
1384  // Original equations
1385  // R = Y + 1.402 V
1386  // G = Y - 0.344 U - 0.714 V
1387  // B = Y + 1.772 U
1388  int R = Y0 + V2;
1389  if ((R >> 8) > 0)
1390  R = 255;
1391  else if (R < 0)
1392  R = 0;
1393 
1394  int G = Y0 + UV;
1395  if ((G >> 8) > 0)
1396  G = 255;
1397  else if (G < 0)
1398  G = 0;
1399 
1400  int B = Y0 + U5;
1401  if ((B >> 8) > 0)
1402  B = 255;
1403  else if (B < 0)
1404  B = 0;
1405 
1406  *rgba++ = (unsigned char)R;
1407  *rgba++ = (unsigned char)G;
1408  *rgba++ = (unsigned char)B;
1409  *rgba++ = vpRGBa::alpha_default;
1410 
1411  //---
1412  R = Y1 + V2;
1413  if ((R >> 8) > 0)
1414  R = 255;
1415  else if (R < 0)
1416  R = 0;
1417 
1418  G = Y1 + UV;
1419  if ((G >> 8) > 0)
1420  G = 255;
1421  else if (G < 0)
1422  G = 0;
1423 
1424  B = Y1 + U5;
1425  if ((B >> 8) > 0)
1426  B = 255;
1427  else if (B < 0)
1428  B = 0;
1429 
1430  *rgba++ = (unsigned char)R;
1431  *rgba++ = (unsigned char)G;
1432  *rgba++ = (unsigned char)B;
1433  *rgba++ = vpRGBa::alpha_default;
1434 
1435  //---
1436  R = Y2 + V2;
1437  if ((R >> 8) > 0)
1438  R = 255;
1439  else if (R < 0)
1440  R = 0;
1441 
1442  G = Y2 + UV;
1443  if ((G >> 8) > 0)
1444  G = 255;
1445  else if (G < 0)
1446  G = 0;
1447 
1448  B = Y2 + U5;
1449  if ((B >> 8) > 0)
1450  B = 255;
1451  else if (B < 0)
1452  B = 0;
1453 
1454  *rgba++ = (unsigned char)R;
1455  *rgba++ = (unsigned char)G;
1456  *rgba++ = (unsigned char)B;
1457  *rgba++ = vpRGBa::alpha_default;
1458 
1459  //---
1460  R = Y3 + V2;
1461  if ((R >> 8) > 0)
1462  R = 255;
1463  else if (R < 0)
1464  R = 0;
1465 
1466  G = Y3 + UV;
1467  if ((G >> 8) > 0)
1468  G = 255;
1469  else if (G < 0)
1470  G = 0;
1471 
1472  B = Y3 + U5;
1473  if ((B >> 8) > 0)
1474  B = 255;
1475  else if (B < 0)
1476  B = 0;
1477 
1478  *rgba++ = (unsigned char)R;
1479  *rgba++ = (unsigned char)G;
1480  *rgba++ = (unsigned char)B;
1481  *rgba++ = vpRGBa::alpha_default;
1482  }
1483 #else
1484  // tres tres lent ....
1485  unsigned int i = 0, j = 0;
1486  unsigned char r, g, b;
1487  while (j < numpixels * 3 / 2) {
1488 
1489  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 3], r, g, b);
1490  rgba[i] = r;
1491  rgba[i + 1] = g;
1492  rgba[i + 2] = b;
1493  rgba[i + 3] = vpRGBa::alpha_default;
1494  i += 4;
1495 
1496  YUVToRGB(yuv[j + 2], yuv[j], yuv[j + 3], r, g, b);
1497  rgba[i] = r;
1498  rgba[i + 1] = g;
1499  rgba[i + 2] = b;
1500  rgba[i + 3] = vpRGBa::alpha_default;
1501  i += 4;
1502 
1503  YUVToRGB(yuv[j + 4], yuv[j], yuv[j + 3], r, g, b);
1504  rgba[i] = r;
1505  rgba[i + 1] = g;
1506  rgba[i + 2] = b;
1507  rgba[i + 3] = vpRGBa::alpha_default;
1508  i += 4;
1509 
1510  YUVToRGB(yuv[j + 5], yuv[j], yuv[j + 3], r, g, b);
1511  rgba[i] = r;
1512  rgba[i + 1] = g;
1513  rgba[i + 2] = b;
1514  rgba[i + 3] = vpRGBa::alpha_default;
1515  i += 4;
1516 
1517  j += 6;
1518  }
1519 #endif
1520 }
1521 
1530 void vpImageConvert::YUV422ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
1531 {
1532 
1533 #if 1
1534  // std::cout << "call optimized convertYUV422ToRGBa()" << std::endl;
1535  for (unsigned int i = size / 2; i; i--) {
1536  int U = (int)((*yuv++ - 128) * 0.354);
1537  int U5 = 5 * U;
1538  int Y0 = *yuv++;
1539  int V = (int)((*yuv++ - 128) * 0.707);
1540  int V2 = 2 * V;
1541  int Y1 = *yuv++;
1542  int UV = -U - V;
1543 
1544  //---
1545  int R = Y0 + V2;
1546  if ((R >> 8) > 0)
1547  R = 255;
1548  else if (R < 0)
1549  R = 0;
1550 
1551  int G = Y0 + UV;
1552  if ((G >> 8) > 0)
1553  G = 255;
1554  else if (G < 0)
1555  G = 0;
1556 
1557  int B = Y0 + U5;
1558  if ((B >> 8) > 0)
1559  B = 255;
1560  else if (B < 0)
1561  B = 0;
1562 
1563  *rgba++ = (unsigned char)R;
1564  *rgba++ = (unsigned char)G;
1565  *rgba++ = (unsigned char)B;
1566  *rgba++ = vpRGBa::alpha_default;
1567 
1568  //---
1569  R = Y1 + V2;
1570  if ((R >> 8) > 0)
1571  R = 255;
1572  else if (R < 0)
1573  R = 0;
1574 
1575  G = Y1 + UV;
1576  if ((G >> 8) > 0)
1577  G = 255;
1578  else if (G < 0)
1579  G = 0;
1580 
1581  B = Y1 + U5;
1582  if ((B >> 8) > 0)
1583  B = 255;
1584  else if (B < 0)
1585  B = 0;
1586 
1587  *rgba++ = (unsigned char)R;
1588  *rgba++ = (unsigned char)G;
1589  *rgba++ = (unsigned char)B;
1590  *rgba++ = vpRGBa::alpha_default;
1591  }
1592 
1593 #else
1594  // tres tres lent ....
1595  unsigned int i = 0, j = 0;
1596  unsigned char r, g, b;
1597 
1598  while (j < size * 2) {
1599 
1600  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 2], r, g, b);
1601  rgba[i] = r;
1602  rgba[i + 1] = g;
1603  rgba[i + 2] = b;
1604  rgba[i + 3] = vpRGBa::alpha_default;
1605  i += 4;
1606 
1607  YUVToRGB(yuv[j + 3], yuv[j], yuv[j + 2], r, g, b);
1608  rgba[i] = r;
1609  rgba[i + 1] = g;
1610  rgba[i + 2] = b;
1611  rgba[i + 3] = vpRGBa::alpha_default;
1612  i += 4;
1613  j += 4;
1614  }
1615 #endif
1616 }
1617 
1624 void vpImageConvert::YUV411ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
1625 {
1626  unsigned int i = 0, j = 0;
1627  while (j < size * 3 / 2) {
1628  grey[i] = yuv[j + 1];
1629  grey[i + 1] = yuv[j + 2];
1630  grey[i + 2] = yuv[j + 4];
1631  grey[i + 3] = yuv[j + 5];
1632 
1633  i += 4;
1634 
1635  j += 6;
1636  }
1637 }
1638 
1647 void vpImageConvert::YUV422ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
1648 {
1649 #if 1
1650  // std::cout << "call optimized convertYUV422ToRGB()" << std::endl;
1651  for (unsigned int i = size / 2; i; i--) {
1652  int U = (int)((*yuv++ - 128) * 0.354);
1653  int U5 = 5 * U;
1654  int Y0 = *yuv++;
1655  int V = (int)((*yuv++ - 128) * 0.707);
1656  int V2 = 2 * V;
1657  int Y1 = *yuv++;
1658  int UV = -U - V;
1659 
1660  //---
1661  int R = Y0 + V2;
1662  if ((R >> 8) > 0)
1663  R = 255;
1664  else if (R < 0)
1665  R = 0;
1666 
1667  int G = Y0 + UV;
1668  if ((G >> 8) > 0)
1669  G = 255;
1670  else if (G < 0)
1671  G = 0;
1672 
1673  int B = Y0 + U5;
1674  if ((B >> 8) > 0)
1675  B = 255;
1676  else if (B < 0)
1677  B = 0;
1678 
1679  *rgb++ = (unsigned char)R;
1680  *rgb++ = (unsigned char)G;
1681  *rgb++ = (unsigned char)B;
1682 
1683  //---
1684  R = Y1 + V2;
1685  if ((R >> 8) > 0)
1686  R = 255;
1687  else if (R < 0)
1688  R = 0;
1689 
1690  G = Y1 + UV;
1691  if ((G >> 8) > 0)
1692  G = 255;
1693  else if (G < 0)
1694  G = 0;
1695 
1696  B = Y1 + U5;
1697  if ((B >> 8) > 0)
1698  B = 255;
1699  else if (B < 0)
1700  B = 0;
1701 
1702  *rgb++ = (unsigned char)R;
1703  *rgb++ = (unsigned char)G;
1704  *rgb++ = (unsigned char)B;
1705  }
1706 
1707 #else
1708  // tres tres lent ....
1709  unsigned int i = 0, j = 0;
1710  unsigned char r, g, b;
1711 
1712  while (j < size * 2) {
1713 
1714  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 2], r, g, b);
1715  rgb[i] = r;
1716  rgb[i + 1] = g;
1717  rgb[i + 2] = b;
1718  i += 3;
1719 
1720  YUVToRGB(yuv[j + 3], 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  j += 4;
1726  }
1727 #endif
1728 }
1729 
1738 void vpImageConvert::YUV422ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
1739 {
1740  unsigned int i = 0, j = 0;
1741 
1742  while (j < size * 2) {
1743  grey[i++] = yuv[j + 1];
1744  grey[i++] = yuv[j + 3];
1745  j += 4;
1746  }
1747 }
1748 
1755 void vpImageConvert::YUV411ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
1756 {
1757 #if 1
1758  // std::cout << "call optimized ConvertYUV411ToRGB()" << std::endl;
1759  for (unsigned int i = size / 4; i; i--) {
1760  int U = (int)((*yuv++ - 128) * 0.354);
1761  int U5 = 5 * U;
1762  int Y0 = *yuv++;
1763  int Y1 = *yuv++;
1764  int V = (int)((*yuv++ - 128) * 0.707);
1765  int V2 = 2 * V;
1766  int Y2 = *yuv++;
1767  int Y3 = *yuv++;
1768  int UV = -U - V;
1769 
1770  // Original equations
1771  // R = Y + 1.402 V
1772  // G = Y - 0.344 U - 0.714 V
1773  // B = Y + 1.772 U
1774  int R = Y0 + V2;
1775  if ((R >> 8) > 0)
1776  R = 255;
1777  else if (R < 0)
1778  R = 0;
1779 
1780  int G = Y0 + UV;
1781  if ((G >> 8) > 0)
1782  G = 255;
1783  else if (G < 0)
1784  G = 0;
1785 
1786  int B = Y0 + U5;
1787  if ((B >> 8) > 0)
1788  B = 255;
1789  else if (B < 0)
1790  B = 0;
1791 
1792  *rgb++ = (unsigned char)R;
1793  *rgb++ = (unsigned char)G;
1794  *rgb++ = (unsigned char)B;
1795 
1796  //---
1797  R = Y1 + V2;
1798  if ((R >> 8) > 0)
1799  R = 255;
1800  else if (R < 0)
1801  R = 0;
1802 
1803  G = Y1 + UV;
1804  if ((G >> 8) > 0)
1805  G = 255;
1806  else if (G < 0)
1807  G = 0;
1808 
1809  B = Y1 + U5;
1810  if ((B >> 8) > 0)
1811  B = 255;
1812  else if (B < 0)
1813  B = 0;
1814 
1815  *rgb++ = (unsigned char)R;
1816  *rgb++ = (unsigned char)G;
1817  *rgb++ = (unsigned char)B;
1818 
1819  //---
1820  R = Y2 + V2;
1821  if ((R >> 8) > 0)
1822  R = 255;
1823  else if (R < 0)
1824  R = 0;
1825 
1826  G = Y2 + UV;
1827  if ((G >> 8) > 0)
1828  G = 255;
1829  else if (G < 0)
1830  G = 0;
1831 
1832  B = Y2 + U5;
1833  if ((B >> 8) > 0)
1834  B = 255;
1835  else if (B < 0)
1836  B = 0;
1837 
1838  *rgb++ = (unsigned char)R;
1839  *rgb++ = (unsigned char)G;
1840  *rgb++ = (unsigned char)B;
1841 
1842  //---
1843  R = Y3 + V2;
1844  if ((R >> 8) > 0)
1845  R = 255;
1846  else if (R < 0)
1847  R = 0;
1848 
1849  G = Y3 + UV;
1850  if ((G >> 8) > 0)
1851  G = 255;
1852  else if (G < 0)
1853  G = 0;
1854 
1855  B = Y3 + U5;
1856  if ((B >> 8) > 0)
1857  B = 255;
1858  else if (B < 0)
1859  B = 0;
1860 
1861  *rgb++ = (unsigned char)R;
1862  *rgb++ = (unsigned char)G;
1863  *rgb++ = (unsigned char)B;
1864  }
1865 #else
1866  // tres tres lent ....
1867 
1868  unsigned int i = 0, j = 0;
1869  unsigned char r, g, b;
1870 
1871  while (j < size * 3 / 2) {
1872  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 3], r, g, b);
1873  rgb[i] = r;
1874  rgb[i + 1] = g;
1875  rgb[i + 2] = b;
1876  i += 3;
1877 
1878  YUVToRGB(yuv[j + 2], 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 + 4], 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 + 5], 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  // TRACE("r= %d g=%d b=%d", r, g, b);
1896 
1897  j += 6;
1898  }
1899 #endif
1900 }
1901 
1909 void vpImageConvert::YUV420ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
1910 {
1911  // std::cout << "call optimized ConvertYUV420ToRGBa()" << std::endl;
1912  int U, V, R, G, B, V2, U5, UV;
1913  int Y0, Y1, Y2, Y3;
1914  unsigned int size = width * height;
1915  unsigned char *iU = yuv + size;
1916  unsigned char *iV = yuv + 5 * size / 4;
1917  for (unsigned int i = 0; i < height / 2; i++) {
1918  for (unsigned int j = 0; j < width / 2; j++) {
1919  U = (int)((*iU++ - 128) * 0.354);
1920  U5 = 5 * U;
1921  V = (int)((*iV++ - 128) * 0.707);
1922  V2 = 2 * V;
1923  UV = -U - V;
1924  Y0 = *yuv++;
1925  Y1 = *yuv;
1926  yuv = yuv + width - 1;
1927  Y2 = *yuv++;
1928  Y3 = *yuv;
1929  yuv = yuv - width + 1;
1930 
1931  // Original equations
1932  // R = Y + 1.402 V
1933  // G = Y - 0.344 U - 0.714 V
1934  // B = Y + 1.772 U
1935  R = Y0 + V2;
1936  if ((R >> 8) > 0)
1937  R = 255;
1938  else if (R < 0)
1939  R = 0;
1940 
1941  G = Y0 + UV;
1942  if ((G >> 8) > 0)
1943  G = 255;
1944  else if (G < 0)
1945  G = 0;
1946 
1947  B = Y0 + U5;
1948  if ((B >> 8) > 0)
1949  B = 255;
1950  else if (B < 0)
1951  B = 0;
1952 
1953  *rgba++ = (unsigned char)R;
1954  *rgba++ = (unsigned char)G;
1955  *rgba++ = (unsigned char)B;
1956  *rgba++ = vpRGBa::alpha_default;
1957 
1958  //---
1959  R = Y1 + V2;
1960  if ((R >> 8) > 0)
1961  R = 255;
1962  else if (R < 0)
1963  R = 0;
1964 
1965  G = Y1 + UV;
1966  if ((G >> 8) > 0)
1967  G = 255;
1968  else if (G < 0)
1969  G = 0;
1970 
1971  B = Y1 + U5;
1972  if ((B >> 8) > 0)
1973  B = 255;
1974  else if (B < 0)
1975  B = 0;
1976 
1977  *rgba++ = (unsigned char)R;
1978  *rgba++ = (unsigned char)G;
1979  *rgba++ = (unsigned char)B;
1980  *rgba = vpRGBa::alpha_default;
1981  rgba = rgba + 4 * width - 7;
1982 
1983  //---
1984  R = Y2 + V2;
1985  if ((R >> 8) > 0)
1986  R = 255;
1987  else if (R < 0)
1988  R = 0;
1989 
1990  G = Y2 + UV;
1991  if ((G >> 8) > 0)
1992  G = 255;
1993  else if (G < 0)
1994  G = 0;
1995 
1996  B = Y2 + U5;
1997  if ((B >> 8) > 0)
1998  B = 255;
1999  else if (B < 0)
2000  B = 0;
2001 
2002  *rgba++ = (unsigned char)R;
2003  *rgba++ = (unsigned char)G;
2004  *rgba++ = (unsigned char)B;
2005  *rgba++ = vpRGBa::alpha_default;
2006 
2007  //---
2008  R = Y3 + V2;
2009  if ((R >> 8) > 0)
2010  R = 255;
2011  else if (R < 0)
2012  R = 0;
2013 
2014  G = Y3 + UV;
2015  if ((G >> 8) > 0)
2016  G = 255;
2017  else if (G < 0)
2018  G = 0;
2019 
2020  B = Y3 + U5;
2021  if ((B >> 8) > 0)
2022  B = 255;
2023  else if (B < 0)
2024  B = 0;
2025 
2026  *rgba++ = (unsigned char)R;
2027  *rgba++ = (unsigned char)G;
2028  *rgba++ = (unsigned char)B;
2029  *rgba = vpRGBa::alpha_default;
2030  rgba = rgba - 4 * width + 1;
2031  }
2032  yuv += width;
2033  rgba += 4 * width;
2034  }
2035 }
2041 void vpImageConvert::YUV420ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
2042 {
2043  // std::cout << "call optimized ConvertYUV420ToRGB()" << std::endl;
2044  int U, V, R, G, B, V2, U5, UV;
2045  int Y0, Y1, Y2, Y3;
2046  unsigned int size = width * height;
2047  unsigned char *iU = yuv + size;
2048  unsigned char *iV = yuv + 5 * size / 4;
2049  for (unsigned int i = 0; i < height / 2; i++) {
2050  for (unsigned int j = 0; j < width / 2; j++) {
2051  U = (int)((*iU++ - 128) * 0.354);
2052  U5 = 5 * U;
2053  V = (int)((*iV++ - 128) * 0.707);
2054  V2 = 2 * V;
2055  UV = -U - V;
2056  Y0 = *yuv++;
2057  Y1 = *yuv;
2058  yuv = yuv + width - 1;
2059  Y2 = *yuv++;
2060  Y3 = *yuv;
2061  yuv = yuv - width + 1;
2062 
2063  // Original equations
2064  // R = Y + 1.402 V
2065  // G = Y - 0.344 U - 0.714 V
2066  // B = Y + 1.772 U
2067  R = Y0 + V2;
2068  if ((R >> 8) > 0)
2069  R = 255;
2070  else if (R < 0)
2071  R = 0;
2072 
2073  G = Y0 + UV;
2074  if ((G >> 8) > 0)
2075  G = 255;
2076  else if (G < 0)
2077  G = 0;
2078 
2079  B = Y0 + U5;
2080  if ((B >> 8) > 0)
2081  B = 255;
2082  else if (B < 0)
2083  B = 0;
2084 
2085  *rgb++ = (unsigned char)R;
2086  *rgb++ = (unsigned char)G;
2087  *rgb++ = (unsigned char)B;
2088 
2089  //---
2090  R = Y1 + V2;
2091  if ((R >> 8) > 0)
2092  R = 255;
2093  else if (R < 0)
2094  R = 0;
2095 
2096  G = Y1 + UV;
2097  if ((G >> 8) > 0)
2098  G = 255;
2099  else if (G < 0)
2100  G = 0;
2101 
2102  B = Y1 + U5;
2103  if ((B >> 8) > 0)
2104  B = 255;
2105  else if (B < 0)
2106  B = 0;
2107 
2108  *rgb++ = (unsigned char)R;
2109  *rgb++ = (unsigned char)G;
2110  *rgb = (unsigned char)B;
2111  rgb = rgb + 3 * width - 5;
2112 
2113  //---
2114  R = Y2 + V2;
2115  if ((R >> 8) > 0)
2116  R = 255;
2117  else if (R < 0)
2118  R = 0;
2119 
2120  G = Y2 + UV;
2121  if ((G >> 8) > 0)
2122  G = 255;
2123  else if (G < 0)
2124  G = 0;
2125 
2126  B = Y2 + U5;
2127  if ((B >> 8) > 0)
2128  B = 255;
2129  else if (B < 0)
2130  B = 0;
2131 
2132  *rgb++ = (unsigned char)R;
2133  *rgb++ = (unsigned char)G;
2134  *rgb++ = (unsigned char)B;
2135 
2136  //---
2137  R = Y3 + V2;
2138  if ((R >> 8) > 0)
2139  R = 255;
2140  else if (R < 0)
2141  R = 0;
2142 
2143  G = Y3 + UV;
2144  if ((G >> 8) > 0)
2145  G = 255;
2146  else if (G < 0)
2147  G = 0;
2148 
2149  B = Y3 + U5;
2150  if ((B >> 8) > 0)
2151  B = 255;
2152  else if (B < 0)
2153  B = 0;
2154 
2155  *rgb++ = (unsigned char)R;
2156  *rgb++ = (unsigned char)G;
2157  *rgb = (unsigned char)B;
2158  rgb = rgb - 3 * width + 1;
2159  }
2160  yuv += width;
2161  rgb += 3 * width;
2162  }
2163 }
2164 
2170 void vpImageConvert::YUV420ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
2171 {
2172  for (unsigned int i = 0; i < size; i++) {
2173  *grey++ = *yuv++;
2174  }
2175 }
2183 void vpImageConvert::YUV444ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
2184 {
2185  for (unsigned int i = 0; i < size; i++) {
2186  int U = (int)((*yuv++ - 128) * 0.354);
2187  int U5 = 5 * U;
2188  int Y = *yuv++;
2189  int V = (int)((*yuv++ - 128) * 0.707);
2190  int V2 = 2 * V;
2191  int UV = -U - V;
2192 
2193  // Original equations
2194  // R = Y + 1.402 V
2195  // G = Y - 0.344 U - 0.714 V
2196  // B = Y + 1.772 U
2197  int R = Y + V2;
2198  if ((R >> 8) > 0)
2199  R = 255;
2200  else if (R < 0)
2201  R = 0;
2202 
2203  int G = Y + UV;
2204  if ((G >> 8) > 0)
2205  G = 255;
2206  else if (G < 0)
2207  G = 0;
2208 
2209  int B = Y + U5;
2210  if ((B >> 8) > 0)
2211  B = 255;
2212  else if (B < 0)
2213  B = 0;
2214 
2215  *rgba++ = (unsigned char)R;
2216  *rgba++ = (unsigned char)G;
2217  *rgba++ = (unsigned char)B;
2218  *rgba++ = vpRGBa::alpha_default;
2219  }
2220 }
2226 void vpImageConvert::YUV444ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
2227 {
2228  for (unsigned int i = 0; i < size; i++) {
2229  int U = (int)((*yuv++ - 128) * 0.354);
2230  int U5 = 5 * U;
2231  int Y = *yuv++;
2232  int V = (int)((*yuv++ - 128) * 0.707);
2233  int V2 = 2 * V;
2234  int UV = -U - V;
2235 
2236  // Original equations
2237  // R = Y + 1.402 V
2238  // G = Y - 0.344 U - 0.714 V
2239  // B = Y + 1.772 U
2240  int R = Y + V2;
2241  if ((R >> 8) > 0)
2242  R = 255;
2243  else if (R < 0)
2244  R = 0;
2245 
2246  int G = Y + UV;
2247  if ((G >> 8) > 0)
2248  G = 255;
2249  else if (G < 0)
2250  G = 0;
2251 
2252  int B = Y + U5;
2253  if ((B >> 8) > 0)
2254  B = 255;
2255  else if (B < 0)
2256  B = 0;
2257 
2258  *rgb++ = (unsigned char)R;
2259  *rgb++ = (unsigned char)G;
2260  *rgb++ = (unsigned char)B;
2261  }
2262 }
2263 
2269 void vpImageConvert::YUV444ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
2270 {
2271  yuv++;
2272  for (unsigned int i = 0; i < size; i++) {
2273  *grey++ = *yuv;
2274  yuv = yuv + 3;
2275  }
2276 }
2277 
2285 void vpImageConvert::YV12ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
2286 {
2287  // std::cout << "call optimized ConvertYV12ToRGBa()" << std::endl;
2288  int U, V, R, G, B, V2, U5, UV;
2289  int Y0, Y1, Y2, Y3;
2290  unsigned int size = width * height;
2291  unsigned char *iV = yuv + size;
2292  unsigned char *iU = yuv + 5 * size / 4;
2293  for (unsigned int i = 0; i < height / 2; i++) {
2294  for (unsigned int j = 0; j < width / 2; j++) {
2295  U = (int)((*iU++ - 128) * 0.354);
2296  U5 = 5 * U;
2297  V = (int)((*iV++ - 128) * 0.707);
2298  V2 = 2 * V;
2299  UV = -U - V;
2300  Y0 = *yuv++;
2301  Y1 = *yuv;
2302  yuv = yuv + width - 1;
2303  Y2 = *yuv++;
2304  Y3 = *yuv;
2305  yuv = yuv - width + 1;
2306 
2307  // Original equations
2308  // R = Y + 1.402 V
2309  // G = Y - 0.344 U - 0.714 V
2310  // B = Y + 1.772 U
2311  R = Y0 + V2;
2312  if ((R >> 8) > 0)
2313  R = 255;
2314  else if (R < 0)
2315  R = 0;
2316 
2317  G = Y0 + UV;
2318  if ((G >> 8) > 0)
2319  G = 255;
2320  else if (G < 0)
2321  G = 0;
2322 
2323  B = Y0 + U5;
2324  if ((B >> 8) > 0)
2325  B = 255;
2326  else if (B < 0)
2327  B = 0;
2328 
2329  *rgba++ = (unsigned char)R;
2330  *rgba++ = (unsigned char)G;
2331  *rgba++ = (unsigned char)B;
2332  *rgba++ = vpRGBa::alpha_default;
2333 
2334  //---
2335  R = Y1 + V2;
2336  if ((R >> 8) > 0)
2337  R = 255;
2338  else if (R < 0)
2339  R = 0;
2340 
2341  G = Y1 + UV;
2342  if ((G >> 8) > 0)
2343  G = 255;
2344  else if (G < 0)
2345  G = 0;
2346 
2347  B = Y1 + U5;
2348  if ((B >> 8) > 0)
2349  B = 255;
2350  else if (B < 0)
2351  B = 0;
2352 
2353  *rgba++ = (unsigned char)R;
2354  *rgba++ = (unsigned char)G;
2355  *rgba++ = (unsigned char)B;
2356  *rgba = 0;
2357  rgba = rgba + 4 * width - 7;
2358 
2359  //---
2360  R = Y2 + V2;
2361  if ((R >> 8) > 0)
2362  R = 255;
2363  else if (R < 0)
2364  R = 0;
2365 
2366  G = Y2 + UV;
2367  if ((G >> 8) > 0)
2368  G = 255;
2369  else if (G < 0)
2370  G = 0;
2371 
2372  B = Y2 + U5;
2373  if ((B >> 8) > 0)
2374  B = 255;
2375  else if (B < 0)
2376  B = 0;
2377 
2378  *rgba++ = (unsigned char)R;
2379  *rgba++ = (unsigned char)G;
2380  *rgba++ = (unsigned char)B;
2381  *rgba++ = vpRGBa::alpha_default;
2382 
2383  //---
2384  R = Y3 + V2;
2385  if ((R >> 8) > 0)
2386  R = 255;
2387  else if (R < 0)
2388  R = 0;
2389 
2390  G = Y3 + UV;
2391  if ((G >> 8) > 0)
2392  G = 255;
2393  else if (G < 0)
2394  G = 0;
2395 
2396  B = Y3 + U5;
2397  if ((B >> 8) > 0)
2398  B = 255;
2399  else if (B < 0)
2400  B = 0;
2401 
2402  *rgba++ = (unsigned char)R;
2403  *rgba++ = (unsigned char)G;
2404  *rgba++ = (unsigned char)B;
2405  *rgba = vpRGBa::alpha_default;
2406  rgba = rgba - 4 * width + 1;
2407  }
2408  yuv += width;
2409  rgba += 4 * width;
2410  }
2411 }
2417 void vpImageConvert::YV12ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int height, unsigned int width)
2418 {
2419  // std::cout << "call optimized ConvertYV12ToRGB()" << std::endl;
2420  int U, V, R, G, B, V2, U5, UV;
2421  int Y0, Y1, Y2, Y3;
2422  unsigned int size = width * height;
2423  unsigned char *iV = yuv + size;
2424  unsigned char *iU = yuv + 5 * size / 4;
2425  for (unsigned int i = 0; i < height / 2; i++) {
2426  for (unsigned int j = 0; j < width / 2; j++) {
2427  U = (int)((*iU++ - 128) * 0.354);
2428  U5 = 5 * U;
2429  V = (int)((*iV++ - 128) * 0.707);
2430  V2 = 2 * V;
2431  UV = -U - V;
2432  Y0 = *yuv++;
2433  Y1 = *yuv;
2434  yuv = yuv + width - 1;
2435  Y2 = *yuv++;
2436  Y3 = *yuv;
2437  yuv = yuv - width + 1;
2438 
2439  // Original equations
2440  // R = Y + 1.402 V
2441  // G = Y - 0.344 U - 0.714 V
2442  // B = Y + 1.772 U
2443  R = Y0 + V2;
2444  if ((R >> 8) > 0)
2445  R = 255;
2446  else if (R < 0)
2447  R = 0;
2448 
2449  G = Y0 + UV;
2450  if ((G >> 8) > 0)
2451  G = 255;
2452  else if (G < 0)
2453  G = 0;
2454 
2455  B = Y0 + U5;
2456  if ((B >> 8) > 0)
2457  B = 255;
2458  else if (B < 0)
2459  B = 0;
2460 
2461  *rgb++ = (unsigned char)R;
2462  *rgb++ = (unsigned char)G;
2463  *rgb++ = (unsigned char)B;
2464 
2465  //---
2466  R = Y1 + V2;
2467  if ((R >> 8) > 0)
2468  R = 255;
2469  else if (R < 0)
2470  R = 0;
2471 
2472  G = Y1 + UV;
2473  if ((G >> 8) > 0)
2474  G = 255;
2475  else if (G < 0)
2476  G = 0;
2477 
2478  B = Y1 + U5;
2479  if ((B >> 8) > 0)
2480  B = 255;
2481  else if (B < 0)
2482  B = 0;
2483 
2484  *rgb++ = (unsigned char)R;
2485  *rgb++ = (unsigned char)G;
2486  *rgb = (unsigned char)B;
2487  rgb = rgb + 3 * width - 5;
2488 
2489  //---
2490  R = Y2 + V2;
2491  if ((R >> 8) > 0)
2492  R = 255;
2493  else if (R < 0)
2494  R = 0;
2495 
2496  G = Y2 + UV;
2497  if ((G >> 8) > 0)
2498  G = 255;
2499  else if (G < 0)
2500  G = 0;
2501 
2502  B = Y2 + U5;
2503  if ((B >> 8) > 0)
2504  B = 255;
2505  else if (B < 0)
2506  B = 0;
2507 
2508  *rgb++ = (unsigned char)R;
2509  *rgb++ = (unsigned char)G;
2510  *rgb++ = (unsigned char)B;
2511 
2512  //---
2513  R = Y3 + V2;
2514  if ((R >> 8) > 0)
2515  R = 255;
2516  else if (R < 0)
2517  R = 0;
2518 
2519  G = Y3 + UV;
2520  if ((G >> 8) > 0)
2521  G = 255;
2522  else if (G < 0)
2523  G = 0;
2524 
2525  B = Y3 + U5;
2526  if ((B >> 8) > 0)
2527  B = 255;
2528  else if (B < 0)
2529  B = 0;
2530 
2531  *rgb++ = (unsigned char)R;
2532  *rgb++ = (unsigned char)G;
2533  *rgb = (unsigned char)B;
2534  rgb = rgb - 3 * width + 1;
2535  }
2536  yuv += width;
2537  rgb += 3 * width;
2538  }
2539 }
2540 
2548 void vpImageConvert::YVU9ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
2549 {
2550  // std::cout << "call optimized ConvertYVU9ToRGBa()" << std::endl;
2551  int U, V, R, G, B, V2, U5, UV;
2552  int Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9, Y10, Y11, Y12, Y13, Y14, Y15;
2553  unsigned int size = width * height;
2554  unsigned char *iV = yuv + size;
2555  unsigned char *iU = yuv + 17 * size / 16;
2556  for (unsigned int i = 0; i < height / 4; i++) {
2557  for (unsigned int j = 0; j < width / 4; j++) {
2558  U = (int)((*iU++ - 128) * 0.354);
2559  U5 = 5 * U;
2560  V = (int)((*iV++ - 128) * 0.707);
2561  V2 = 2 * V;
2562  UV = -U - V;
2563  Y0 = *yuv++;
2564  Y1 = *yuv++;
2565  Y2 = *yuv++;
2566  Y3 = *yuv;
2567  yuv = yuv + width - 3;
2568  Y4 = *yuv++;
2569  Y5 = *yuv++;
2570  Y6 = *yuv++;
2571  Y7 = *yuv;
2572  yuv = yuv + width - 3;
2573  Y8 = *yuv++;
2574  Y9 = *yuv++;
2575  Y10 = *yuv++;
2576  Y11 = *yuv;
2577  yuv = yuv + width - 3;
2578  Y12 = *yuv++;
2579  Y13 = *yuv++;
2580  Y14 = *yuv++;
2581  Y15 = *yuv;
2582  yuv = yuv - 3 * width + 1;
2583 
2584  // Original equations
2585  // R = Y + 1.402 V
2586  // G = Y - 0.344 U - 0.714 V
2587  // B = Y + 1.772 U
2588  R = Y0 + V2;
2589  if ((R >> 8) > 0)
2590  R = 255;
2591  else if (R < 0)
2592  R = 0;
2593 
2594  G = Y0 + UV;
2595  if ((G >> 8) > 0)
2596  G = 255;
2597  else if (G < 0)
2598  G = 0;
2599 
2600  B = Y0 + U5;
2601  if ((B >> 8) > 0)
2602  B = 255;
2603  else if (B < 0)
2604  B = 0;
2605 
2606  *rgba++ = (unsigned char)R;
2607  *rgba++ = (unsigned char)G;
2608  *rgba++ = (unsigned char)B;
2609  *rgba++ = vpRGBa::alpha_default;
2610 
2611  //---
2612  R = Y1 + V2;
2613  if ((R >> 8) > 0)
2614  R = 255;
2615  else if (R < 0)
2616  R = 0;
2617 
2618  G = Y1 + UV;
2619  if ((G >> 8) > 0)
2620  G = 255;
2621  else if (G < 0)
2622  G = 0;
2623 
2624  B = Y1 + U5;
2625  if ((B >> 8) > 0)
2626  B = 255;
2627  else if (B < 0)
2628  B = 0;
2629 
2630  *rgba++ = (unsigned char)R;
2631  *rgba++ = (unsigned char)G;
2632  *rgba++ = (unsigned char)B;
2633  *rgba++ = vpRGBa::alpha_default;
2634 
2635  //---
2636  R = Y2 + V2;
2637  if ((R >> 8) > 0)
2638  R = 255;
2639  else if (R < 0)
2640  R = 0;
2641 
2642  G = Y2 + UV;
2643  if ((G >> 8) > 0)
2644  G = 255;
2645  else if (G < 0)
2646  G = 0;
2647 
2648  B = Y2 + U5;
2649  if ((B >> 8) > 0)
2650  B = 255;
2651  else if (B < 0)
2652  B = 0;
2653 
2654  *rgba++ = (unsigned char)R;
2655  *rgba++ = (unsigned char)G;
2656  *rgba++ = (unsigned char)B;
2657  *rgba++ = vpRGBa::alpha_default;
2658 
2659  //---
2660  R = Y3 + V2;
2661  if ((R >> 8) > 0)
2662  R = 255;
2663  else if (R < 0)
2664  R = 0;
2665 
2666  G = Y3 + UV;
2667  if ((G >> 8) > 0)
2668  G = 255;
2669  else if (G < 0)
2670  G = 0;
2671 
2672  B = Y3 + U5;
2673  if ((B >> 8) > 0)
2674  B = 255;
2675  else if (B < 0)
2676  B = 0;
2677 
2678  *rgba++ = (unsigned char)R;
2679  *rgba++ = (unsigned char)G;
2680  *rgba++ = (unsigned char)B;
2681  *rgba = vpRGBa::alpha_default;
2682  rgba = rgba + 4 * width - 15;
2683 
2684  R = Y4 + V2;
2685  if ((R >> 8) > 0)
2686  R = 255;
2687  else if (R < 0)
2688  R = 0;
2689 
2690  G = Y4 + UV;
2691  if ((G >> 8) > 0)
2692  G = 255;
2693  else if (G < 0)
2694  G = 0;
2695 
2696  B = Y4 + U5;
2697  if ((B >> 8) > 0)
2698  B = 255;
2699  else if (B < 0)
2700  B = 0;
2701 
2702  *rgba++ = (unsigned char)R;
2703  *rgba++ = (unsigned char)G;
2704  *rgba++ = (unsigned char)B;
2705  *rgba++ = vpRGBa::alpha_default;
2706 
2707  //---
2708  R = Y5 + V2;
2709  if ((R >> 8) > 0)
2710  R = 255;
2711  else if (R < 0)
2712  R = 0;
2713 
2714  G = Y5 + UV;
2715  if ((G >> 8) > 0)
2716  G = 255;
2717  else if (G < 0)
2718  G = 0;
2719 
2720  B = Y5 + U5;
2721  if ((B >> 8) > 0)
2722  B = 255;
2723  else if (B < 0)
2724  B = 0;
2725 
2726  *rgba++ = (unsigned char)R;
2727  *rgba++ = (unsigned char)G;
2728  *rgba++ = (unsigned char)B;
2729  *rgba++ = vpRGBa::alpha_default;
2730 
2731  //---
2732  R = Y6 + V2;
2733  if ((R >> 8) > 0)
2734  R = 255;
2735  else if (R < 0)
2736  R = 0;
2737 
2738  G = Y6 + UV;
2739  if ((G >> 8) > 0)
2740  G = 255;
2741  else if (G < 0)
2742  G = 0;
2743 
2744  B = Y6 + U5;
2745  if ((B >> 8) > 0)
2746  B = 255;
2747  else if (B < 0)
2748  B = 0;
2749 
2750  *rgba++ = (unsigned char)R;
2751  *rgba++ = (unsigned char)G;
2752  *rgba++ = (unsigned char)B;
2753  *rgba++ = vpRGBa::alpha_default;
2754 
2755  //---
2756  R = Y7 + V2;
2757  if ((R >> 8) > 0)
2758  R = 255;
2759  else if (R < 0)
2760  R = 0;
2761 
2762  G = Y7 + UV;
2763  if ((G >> 8) > 0)
2764  G = 255;
2765  else if (G < 0)
2766  G = 0;
2767 
2768  B = Y7 + U5;
2769  if ((B >> 8) > 0)
2770  B = 255;
2771  else if (B < 0)
2772  B = 0;
2773 
2774  *rgba++ = (unsigned char)R;
2775  *rgba++ = (unsigned char)G;
2776  *rgba++ = (unsigned char)B;
2777  *rgba = vpRGBa::alpha_default;
2778  rgba = rgba + 4 * width - 15;
2779 
2780  R = Y8 + V2;
2781  if ((R >> 8) > 0)
2782  R = 255;
2783  else if (R < 0)
2784  R = 0;
2785 
2786  G = Y8 + UV;
2787  if ((G >> 8) > 0)
2788  G = 255;
2789  else if (G < 0)
2790  G = 0;
2791 
2792  B = Y8 + U5;
2793  if ((B >> 8) > 0)
2794  B = 255;
2795  else if (B < 0)
2796  B = 0;
2797 
2798  *rgba++ = (unsigned char)R;
2799  *rgba++ = (unsigned char)G;
2800  *rgba++ = (unsigned char)B;
2801  *rgba++ = vpRGBa::alpha_default;
2802 
2803  //---
2804  R = Y9 + V2;
2805  if ((R >> 8) > 0)
2806  R = 255;
2807  else if (R < 0)
2808  R = 0;
2809 
2810  G = Y9 + UV;
2811  if ((G >> 8) > 0)
2812  G = 255;
2813  else if (G < 0)
2814  G = 0;
2815 
2816  B = Y9 + U5;
2817  if ((B >> 8) > 0)
2818  B = 255;
2819  else if (B < 0)
2820  B = 0;
2821 
2822  *rgba++ = (unsigned char)R;
2823  *rgba++ = (unsigned char)G;
2824  *rgba++ = (unsigned char)B;
2825  *rgba++ = vpRGBa::alpha_default;
2826 
2827  //---
2828  R = Y10 + V2;
2829  if ((R >> 8) > 0)
2830  R = 255;
2831  else if (R < 0)
2832  R = 0;
2833 
2834  G = Y10 + UV;
2835  if ((G >> 8) > 0)
2836  G = 255;
2837  else if (G < 0)
2838  G = 0;
2839 
2840  B = Y10 + U5;
2841  if ((B >> 8) > 0)
2842  B = 255;
2843  else if (B < 0)
2844  B = 0;
2845 
2846  *rgba++ = (unsigned char)R;
2847  *rgba++ = (unsigned char)G;
2848  *rgba++ = (unsigned char)B;
2849  *rgba++ = vpRGBa::alpha_default;
2850 
2851  //---
2852  R = Y11 + V2;
2853  if ((R >> 8) > 0)
2854  R = 255;
2855  else if (R < 0)
2856  R = 0;
2857 
2858  G = Y11 + UV;
2859  if ((G >> 8) > 0)
2860  G = 255;
2861  else if (G < 0)
2862  G = 0;
2863 
2864  B = Y11 + U5;
2865  if ((B >> 8) > 0)
2866  B = 255;
2867  else if (B < 0)
2868  B = 0;
2869 
2870  *rgba++ = (unsigned char)R;
2871  *rgba++ = (unsigned char)G;
2872  *rgba++ = (unsigned char)B;
2873  *rgba = vpRGBa::alpha_default;
2874  rgba = rgba + 4 * width - 15;
2875 
2876  R = Y12 + V2;
2877  if ((R >> 8) > 0)
2878  R = 255;
2879  else if (R < 0)
2880  R = 0;
2881 
2882  G = Y12 + UV;
2883  if ((G >> 8) > 0)
2884  G = 255;
2885  else if (G < 0)
2886  G = 0;
2887 
2888  B = Y12 + U5;
2889  if ((B >> 8) > 0)
2890  B = 255;
2891  else if (B < 0)
2892  B = 0;
2893 
2894  *rgba++ = (unsigned char)R;
2895  *rgba++ = (unsigned char)G;
2896  *rgba++ = (unsigned char)B;
2897  *rgba++ = vpRGBa::alpha_default;
2898 
2899  //---
2900  R = Y13 + V2;
2901  if ((R >> 8) > 0)
2902  R = 255;
2903  else if (R < 0)
2904  R = 0;
2905 
2906  G = Y13 + UV;
2907  if ((G >> 8) > 0)
2908  G = 255;
2909  else if (G < 0)
2910  G = 0;
2911 
2912  B = Y13 + U5;
2913  if ((B >> 8) > 0)
2914  B = 255;
2915  else if (B < 0)
2916  B = 0;
2917 
2918  *rgba++ = (unsigned char)R;
2919  *rgba++ = (unsigned char)G;
2920  *rgba++ = (unsigned char)B;
2921  *rgba++ = vpRGBa::alpha_default;
2922 
2923  //---
2924  R = Y14 + V2;
2925  if ((R >> 8) > 0)
2926  R = 255;
2927  else if (R < 0)
2928  R = 0;
2929 
2930  G = Y14 + UV;
2931  if ((G >> 8) > 0)
2932  G = 255;
2933  else if (G < 0)
2934  G = 0;
2935 
2936  B = Y14 + U5;
2937  if ((B >> 8) > 0)
2938  B = 255;
2939  else if (B < 0)
2940  B = 0;
2941 
2942  *rgba++ = (unsigned char)R;
2943  *rgba++ = (unsigned char)G;
2944  *rgba++ = (unsigned char)B;
2945  *rgba++ = vpRGBa::alpha_default;
2946 
2947  //---
2948  R = Y15 + V2;
2949  if ((R >> 8) > 0)
2950  R = 255;
2951  else if (R < 0)
2952  R = 0;
2953 
2954  G = Y15 + UV;
2955  if ((G >> 8) > 0)
2956  G = 255;
2957  else if (G < 0)
2958  G = 0;
2959 
2960  B = Y15 + U5;
2961  if ((B >> 8) > 0)
2962  B = 255;
2963  else if (B < 0)
2964  B = 0;
2965 
2966  *rgba++ = (unsigned char)R;
2967  *rgba++ = (unsigned char)G;
2968  *rgba++ = (unsigned char)B;
2969  *rgba = vpRGBa::alpha_default;
2970  rgba = rgba - 12 * width + 1;
2971  }
2972  yuv += 3 * width;
2973  rgba += 12 * width;
2974  }
2975 }
2981 void vpImageConvert::YVU9ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int height, unsigned int width)
2982 {
2983  // std::cout << "call optimized ConvertYVU9ToRGB()" << std::endl;
2984  int U, V, R, G, B, V2, U5, UV;
2985  int Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9, Y10, Y11, Y12, Y13, Y14, Y15;
2986  unsigned int size = width * height;
2987  unsigned char *iV = yuv + size;
2988  unsigned char *iU = yuv + 17 * size / 16;
2989  for (unsigned int i = 0; i < height / 4; i++) {
2990  for (unsigned int j = 0; j < width / 4; j++) {
2991  U = (int)((*iU++ - 128) * 0.354);
2992  U5 = 5 * U;
2993  V = (int)((*iV++ - 128) * 0.707);
2994  V2 = 2 * V;
2995  UV = -U - V;
2996  Y0 = *yuv++;
2997  Y1 = *yuv++;
2998  Y2 = *yuv++;
2999  Y3 = *yuv;
3000  yuv = yuv + width - 3;
3001  Y4 = *yuv++;
3002  Y5 = *yuv++;
3003  Y6 = *yuv++;
3004  Y7 = *yuv;
3005  yuv = yuv + width - 3;
3006  Y8 = *yuv++;
3007  Y9 = *yuv++;
3008  Y10 = *yuv++;
3009  Y11 = *yuv;
3010  yuv = yuv + width - 3;
3011  Y12 = *yuv++;
3012  Y13 = *yuv++;
3013  Y14 = *yuv++;
3014  Y15 = *yuv;
3015  yuv = yuv - 3 * width + 1;
3016 
3017  // Original equations
3018  // R = Y + 1.402 V
3019  // G = Y - 0.344 U - 0.714 V
3020  // B = Y + 1.772 U
3021  R = Y0 + V2;
3022  if ((R >> 8) > 0)
3023  R = 255;
3024  else if (R < 0)
3025  R = 0;
3026 
3027  G = Y0 + UV;
3028  if ((G >> 8) > 0)
3029  G = 255;
3030  else if (G < 0)
3031  G = 0;
3032 
3033  B = Y0 + U5;
3034  if ((B >> 8) > 0)
3035  B = 255;
3036  else if (B < 0)
3037  B = 0;
3038 
3039  *rgb++ = (unsigned char)R;
3040  *rgb++ = (unsigned char)G;
3041  *rgb++ = (unsigned char)B;
3042 
3043  //---
3044  R = Y1 + V2;
3045  if ((R >> 8) > 0)
3046  R = 255;
3047  else if (R < 0)
3048  R = 0;
3049 
3050  G = Y1 + UV;
3051  if ((G >> 8) > 0)
3052  G = 255;
3053  else if (G < 0)
3054  G = 0;
3055 
3056  B = Y1 + U5;
3057  if ((B >> 8) > 0)
3058  B = 255;
3059  else if (B < 0)
3060  B = 0;
3061 
3062  *rgb++ = (unsigned char)R;
3063  *rgb++ = (unsigned char)G;
3064  *rgb++ = (unsigned char)B;
3065 
3066  //---
3067  R = Y2 + V2;
3068  if ((R >> 8) > 0)
3069  R = 255;
3070  else if (R < 0)
3071  R = 0;
3072 
3073  G = Y2 + UV;
3074  if ((G >> 8) > 0)
3075  G = 255;
3076  else if (G < 0)
3077  G = 0;
3078 
3079  B = Y2 + U5;
3080  if ((B >> 8) > 0)
3081  B = 255;
3082  else if (B < 0)
3083  B = 0;
3084 
3085  *rgb++ = (unsigned char)R;
3086  *rgb++ = (unsigned char)G;
3087  *rgb++ = (unsigned char)B;
3088 
3089  //---
3090  R = Y3 + V2;
3091  if ((R >> 8) > 0)
3092  R = 255;
3093  else if (R < 0)
3094  R = 0;
3095 
3096  G = Y3 + UV;
3097  if ((G >> 8) > 0)
3098  G = 255;
3099  else if (G < 0)
3100  G = 0;
3101 
3102  B = Y3 + U5;
3103  if ((B >> 8) > 0)
3104  B = 255;
3105  else if (B < 0)
3106  B = 0;
3107 
3108  *rgb++ = (unsigned char)R;
3109  *rgb++ = (unsigned char)G;
3110  *rgb = (unsigned char)B;
3111  rgb = rgb + 3 * width - 11;
3112 
3113  R = Y4 + V2;
3114  if ((R >> 8) > 0)
3115  R = 255;
3116  else if (R < 0)
3117  R = 0;
3118 
3119  G = Y4 + UV;
3120  if ((G >> 8) > 0)
3121  G = 255;
3122  else if (G < 0)
3123  G = 0;
3124 
3125  B = Y4 + U5;
3126  if ((B >> 8) > 0)
3127  B = 255;
3128  else if (B < 0)
3129  B = 0;
3130 
3131  *rgb++ = (unsigned char)R;
3132  *rgb++ = (unsigned char)G;
3133  *rgb++ = (unsigned char)B;
3134 
3135  //---
3136  R = Y5 + V2;
3137  if ((R >> 8) > 0)
3138  R = 255;
3139  else if (R < 0)
3140  R = 0;
3141 
3142  G = Y5 + UV;
3143  if ((G >> 8) > 0)
3144  G = 255;
3145  else if (G < 0)
3146  G = 0;
3147 
3148  B = Y5 + U5;
3149  if ((B >> 8) > 0)
3150  B = 255;
3151  else if (B < 0)
3152  B = 0;
3153 
3154  *rgb++ = (unsigned char)R;
3155  *rgb++ = (unsigned char)G;
3156  *rgb++ = (unsigned char)B;
3157 
3158  //---
3159  R = Y6 + V2;
3160  if ((R >> 8) > 0)
3161  R = 255;
3162  else if (R < 0)
3163  R = 0;
3164 
3165  G = Y6 + UV;
3166  if ((G >> 8) > 0)
3167  G = 255;
3168  else if (G < 0)
3169  G = 0;
3170 
3171  B = Y6 + U5;
3172  if ((B >> 8) > 0)
3173  B = 255;
3174  else if (B < 0)
3175  B = 0;
3176 
3177  *rgb++ = (unsigned char)R;
3178  *rgb++ = (unsigned char)G;
3179  *rgb++ = (unsigned char)B;
3180 
3181  //---
3182  R = Y7 + V2;
3183  if ((R >> 8) > 0)
3184  R = 255;
3185  else if (R < 0)
3186  R = 0;
3187 
3188  G = Y7 + UV;
3189  if ((G >> 8) > 0)
3190  G = 255;
3191  else if (G < 0)
3192  G = 0;
3193 
3194  B = Y7 + U5;
3195  if ((B >> 8) > 0)
3196  B = 255;
3197  else if (B < 0)
3198  B = 0;
3199 
3200  *rgb++ = (unsigned char)R;
3201  *rgb++ = (unsigned char)G;
3202  *rgb = (unsigned char)B;
3203  rgb = rgb + 3 * width - 11;
3204 
3205  R = Y8 + V2;
3206  if ((R >> 8) > 0)
3207  R = 255;
3208  else if (R < 0)
3209  R = 0;
3210 
3211  G = Y8 + UV;
3212  if ((G >> 8) > 0)
3213  G = 255;
3214  else if (G < 0)
3215  G = 0;
3216 
3217  B = Y8 + U5;
3218  if ((B >> 8) > 0)
3219  B = 255;
3220  else if (B < 0)
3221  B = 0;
3222 
3223  *rgb++ = (unsigned char)R;
3224  *rgb++ = (unsigned char)G;
3225  *rgb++ = (unsigned char)B;
3226 
3227  //---
3228  R = Y9 + V2;
3229  if ((R >> 8) > 0)
3230  R = 255;
3231  else if (R < 0)
3232  R = 0;
3233 
3234  G = Y9 + UV;
3235  if ((G >> 8) > 0)
3236  G = 255;
3237  else if (G < 0)
3238  G = 0;
3239 
3240  B = Y9 + U5;
3241  if ((B >> 8) > 0)
3242  B = 255;
3243  else if (B < 0)
3244  B = 0;
3245 
3246  *rgb++ = (unsigned char)R;
3247  *rgb++ = (unsigned char)G;
3248  *rgb++ = (unsigned char)B;
3249 
3250  //---
3251  R = Y10 + V2;
3252  if ((R >> 8) > 0)
3253  R = 255;
3254  else if (R < 0)
3255  R = 0;
3256 
3257  G = Y10 + UV;
3258  if ((G >> 8) > 0)
3259  G = 255;
3260  else if (G < 0)
3261  G = 0;
3262 
3263  B = Y10 + U5;
3264  if ((B >> 8) > 0)
3265  B = 255;
3266  else if (B < 0)
3267  B = 0;
3268 
3269  *rgb++ = (unsigned char)R;
3270  *rgb++ = (unsigned char)G;
3271  *rgb++ = (unsigned char)B;
3272 
3273  //---
3274  R = Y11 + V2;
3275  if ((R >> 8) > 0)
3276  R = 255;
3277  else if (R < 0)
3278  R = 0;
3279 
3280  G = Y11 + UV;
3281  if ((G >> 8) > 0)
3282  G = 255;
3283  else if (G < 0)
3284  G = 0;
3285 
3286  B = Y11 + U5;
3287  if ((B >> 8) > 0)
3288  B = 255;
3289  else if (B < 0)
3290  B = 0;
3291 
3292  *rgb++ = (unsigned char)R;
3293  *rgb++ = (unsigned char)G;
3294  *rgb = (unsigned char)B;
3295  rgb = rgb + 3 * width - 11;
3296 
3297  R = Y12 + V2;
3298  if ((R >> 8) > 0)
3299  R = 255;
3300  else if (R < 0)
3301  R = 0;
3302 
3303  G = Y12 + UV;
3304  if ((G >> 8) > 0)
3305  G = 255;
3306  else if (G < 0)
3307  G = 0;
3308 
3309  B = Y12 + U5;
3310  if ((B >> 8) > 0)
3311  B = 255;
3312  else if (B < 0)
3313  B = 0;
3314 
3315  *rgb++ = (unsigned char)R;
3316  *rgb++ = (unsigned char)G;
3317  *rgb++ = (unsigned char)B;
3318 
3319  //---
3320  R = Y13 + V2;
3321  if ((R >> 8) > 0)
3322  R = 255;
3323  else if (R < 0)
3324  R = 0;
3325 
3326  G = Y13 + UV;
3327  if ((G >> 8) > 0)
3328  G = 255;
3329  else if (G < 0)
3330  G = 0;
3331 
3332  B = Y13 + U5;
3333  if ((B >> 8) > 0)
3334  B = 255;
3335  else if (B < 0)
3336  B = 0;
3337 
3338  *rgb++ = (unsigned char)R;
3339  *rgb++ = (unsigned char)G;
3340  *rgb++ = (unsigned char)B;
3341 
3342  //---
3343  R = Y14 + V2;
3344  if ((R >> 8) > 0)
3345  R = 255;
3346  else if (R < 0)
3347  R = 0;
3348 
3349  G = Y14 + UV;
3350  if ((G >> 8) > 0)
3351  G = 255;
3352  else if (G < 0)
3353  G = 0;
3354 
3355  B = Y14 + U5;
3356  if ((B >> 8) > 0)
3357  B = 255;
3358  else if (B < 0)
3359  B = 0;
3360 
3361  *rgb++ = (unsigned char)R;
3362  *rgb++ = (unsigned char)G;
3363  *rgb++ = (unsigned char)B;
3364 
3365  //---
3366  R = Y15 + V2;
3367  if ((R >> 8) > 0)
3368  R = 255;
3369  else if (R < 0)
3370  R = 0;
3371 
3372  G = Y15 + UV;
3373  if ((G >> 8) > 0)
3374  G = 255;
3375  else if (G < 0)
3376  G = 0;
3377 
3378  B = Y15 + U5;
3379  if ((B >> 8) > 0)
3380  B = 255;
3381  else if (B < 0)
3382  B = 0;
3383 
3384  *rgb++ = (unsigned char)R;
3385  *rgb++ = (unsigned char)G;
3386  *rgb++ = (unsigned char)B;
3387  rgb = rgb - 9 * width + 1;
3388  }
3389  yuv += 3 * width;
3390  rgb += 9 * width;
3391  }
3392 }
3393 
3401 void vpImageConvert::RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
3402 {
3403  unsigned char *pt_input = rgb;
3404  unsigned char *pt_end = rgb + 3 * size;
3405  unsigned char *pt_output = rgba;
3406 
3407  while (pt_input != pt_end) {
3408  *(pt_output++) = *(pt_input++); // R
3409  *(pt_output++) = *(pt_input++); // G
3410  *(pt_output++) = *(pt_input++); // B
3411  *(pt_output++) = vpRGBa::alpha_default; // A
3412  }
3413 }
3414 
3422 void vpImageConvert::RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
3423 {
3424  unsigned char *pt_input = rgba;
3425  unsigned char *pt_end = rgba + 4 * size;
3426  unsigned char *pt_output = rgb;
3427 
3428  while (pt_input != pt_end) {
3429  *(pt_output++) = *(pt_input++); // R
3430  *(pt_output++) = *(pt_input++); // G
3431  *(pt_output++) = *(pt_input++); // B
3432  pt_input++;
3433  }
3434 }
3441 void vpImageConvert::RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int size)
3442 {
3443  bool checkSSSE3 = vpCPUFeatures::checkSSSE3();
3444 #if !VISP_HAVE_SSSE3
3445  checkSSSE3 = false;
3446 #endif
3447 
3448  if (checkSSSE3) {
3449 #if VISP_HAVE_SSSE3
3450  unsigned int i = 0;
3451 
3452  if (size >= 16) {
3453  // Mask to select R component
3454  const __m128i mask_R1 = _mm_set_epi8(-1, -1, -1, -1, 15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1);
3455  const __m128i mask_R2 = _mm_set_epi8(5, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3456  const __m128i mask_R3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1);
3457  const __m128i mask_R4 = _mm_set_epi8(13, -1, 10, -1, 7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1);
3458 
3459  // Mask to select G component
3460  const __m128i mask_G1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 13, -1, 10, -1, 7, -1, 4, -1, 1, -1);
3461  const __m128i mask_G2 = _mm_set_epi8(6, -1, 3, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3462  const __m128i mask_G3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 12, -1, 9, -1);
3463  const __m128i mask_G4 = _mm_set_epi8(14, -1, 11, -1, 8, -1, 5, -1, 2, -1, -1, -1, -1, -1, -1, -1);
3464 
3465  // Mask to select B component
3466  const __m128i mask_B1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1, 5, -1, 2, -1);
3467  const __m128i mask_B2 = _mm_set_epi8(7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3468  const __m128i mask_B3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 10, -1);
3469  const __m128i mask_B4 = _mm_set_epi8(15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1, -1, -1, -1, -1);
3470 
3471  // Mask to select the gray component
3472  const __m128i mask_low1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1);
3473  const __m128i mask_low2 = _mm_set_epi8(15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1);
3474 
3475  // Coefficients RGB to Gray
3476  const __m128i coeff_R = _mm_set_epi16(13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933);
3477  const __m128i coeff_G = _mm_set_epi16((short int)46871, (short int)46871, (short int)46871, (short int)46871,
3478  (short int)46871, (short int)46871, (short int)46871, (short int)46871);
3479  const __m128i coeff_B = _mm_set_epi16(4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732);
3480 
3481  for (; i <= size - 16; i += 16) {
3482  // Process 16 color pixels
3483  const __m128i data1 = _mm_loadu_si128((const __m128i *)rgb);
3484  const __m128i data2 = _mm_loadu_si128((const __m128i *)(rgb + 16));
3485  const __m128i data3 = _mm_loadu_si128((const __m128i *)(rgb + 32));
3486 
3487  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3488  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3489  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3490 
3491  const __m128i grays_0_7 =
3492  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3493  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3494 
3495  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4));
3496  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4));
3497  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4));
3498 
3499  const __m128i grays_8_15 =
3500  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R),
3501  _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G), _mm_mulhi_epu16(blue_8_15, coeff_B)));
3502 
3503  _mm_storeu_si128((__m128i *)grey,
3504  _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1), _mm_shuffle_epi8(grays_8_15, mask_low2)));
3505 
3506  rgb += 48;
3507  grey += 16;
3508  }
3509  }
3510 
3511  for (; i < size; i++) {
3512  *grey = (unsigned char)(0.2126 * (*rgb) + 0.7152 * (*(rgb + 1)) + 0.0722 * (*(rgb + 2)));
3513 
3514  rgb += 3;
3515  ++grey;
3516  }
3517 #endif
3518  } else {
3519  unsigned char *pt_input = rgb;
3520  unsigned char *pt_end = rgb + size * 3;
3521  unsigned char *pt_output = grey;
3522 
3523  while (pt_input != pt_end) {
3524  *pt_output = (unsigned char)(0.2126 * (*pt_input) + 0.7152 * (*(pt_input + 1)) + 0.0722 * (*(pt_input + 2)));
3525  pt_input += 3;
3526  pt_output++;
3527  }
3528  }
3529 }
3537 void vpImageConvert::RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int size)
3538 {
3539  bool checkSSSE3 = vpCPUFeatures::checkSSSE3();
3540 #if !VISP_HAVE_SSSE3
3541  checkSSSE3 = false;
3542 #endif
3543 
3544  if (checkSSSE3) {
3545 #if VISP_HAVE_SSSE3
3546  unsigned int i = 0;
3547 
3548  if (size >= 16) {
3549  // Mask to select R component
3550  const __m128i mask_R1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 12, -1, 8, -1, 4, -1, 0, -1);
3551  const __m128i mask_R2 = _mm_set_epi8(12, -1, 8, -1, 4, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3552 
3553  // Mask to select G component
3554  const __m128i mask_G1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 9, -1, 5, -1, 1, -1);
3555  const __m128i mask_G2 = _mm_set_epi8(13, -1, 9, -1, 5, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3556 
3557  // Mask to select B component
3558  const __m128i mask_B1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 10, -1, 6, -1, 2, -1);
3559  const __m128i mask_B2 = _mm_set_epi8(14, -1, 10, -1, 6, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3560 
3561  // Mask to select the gray component
3562  const __m128i mask_low1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1);
3563  const __m128i mask_low2 = _mm_set_epi8(15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1);
3564 
3565  // Coefficients RGB to Gray
3566  const __m128i coeff_R = _mm_set_epi16(13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933);
3567  const __m128i coeff_G = _mm_set_epi16((short int)46871, (short int)46871, (short int)46871, (short int)46871,
3568  (short int)46871, (short int)46871, (short int)46871, (short int)46871);
3569  const __m128i coeff_B = _mm_set_epi16(4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732);
3570 
3571  for (; i <= size - 16; i += 16) {
3572  // Process 2*4 color pixels
3573  const __m128i data1 = _mm_loadu_si128((const __m128i *)rgba);
3574  const __m128i data2 = _mm_loadu_si128((const __m128i *)(rgba + 16));
3575 
3576  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3577  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3578  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3579 
3580  const __m128i grays_0_7 =
3581  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3582  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3583 
3584  // Process next 2*4 color pixels
3585  const __m128i data3 = _mm_loadu_si128((const __m128i *)(rgba + 32));
3586  const __m128i data4 = _mm_loadu_si128((const __m128i *)(rgba + 48));
3587 
3588  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data3, mask_R1), _mm_shuffle_epi8(data4, mask_R2));
3589  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data3, mask_G1), _mm_shuffle_epi8(data4, mask_G2));
3590  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data3, mask_B1), _mm_shuffle_epi8(data4, mask_B2));
3591 
3592  const __m128i grays_8_15 =
3593  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R),
3594  _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G), _mm_mulhi_epu16(blue_8_15, coeff_B)));
3595 
3596  _mm_storeu_si128((__m128i *)grey,
3597  _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1), _mm_shuffle_epi8(grays_8_15, mask_low2)));
3598 
3599  rgba += 64;
3600  grey += 16;
3601  }
3602  }
3603 
3604  for (; i < size; i++) {
3605  *grey = (unsigned char)(0.2126 * (*rgba) + 0.7152 * (*(rgba + 1)) + 0.0722 * (*(rgba + 2)));
3606 
3607  rgba += 4;
3608  ++grey;
3609  }
3610 #endif
3611  } else {
3612  unsigned char *pt_input = rgba;
3613  unsigned char *pt_end = rgba + size * 4;
3614  unsigned char *pt_output = grey;
3615 
3616  while (pt_input != pt_end) {
3617  *pt_output = (unsigned char)(0.2126 * (*pt_input) + 0.7152 * (*(pt_input + 1)) + 0.0722 * (*(pt_input + 2)));
3618  pt_input += 4;
3619  pt_output++;
3620  }
3621  }
3622 }
3623 
3629 void vpImageConvert::GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int size)
3630 {
3631  unsigned char *pt_input = grey;
3632  unsigned char *pt_end = grey + size;
3633  unsigned char *pt_output = rgba;
3634 
3635  while (pt_input != pt_end) {
3636  unsigned char p = *pt_input;
3637  *(pt_output) = p; // R
3638  *(pt_output + 1) = p; // G
3639  *(pt_output + 2) = p; // B
3640  *(pt_output + 3) = vpRGBa::alpha_default; // A
3641 
3642  pt_input++;
3643  pt_output += 4;
3644  }
3645 }
3646 
3651 void vpImageConvert::GreyToRGB(unsigned char *grey, unsigned char *rgb, unsigned int size)
3652 {
3653  unsigned char *pt_input = grey;
3654  unsigned char *pt_end = grey + size;
3655  unsigned char *pt_output = rgb;
3656 
3657  while (pt_input != pt_end) {
3658  unsigned char p = *pt_input;
3659  *(pt_output) = p; // R
3660  *(pt_output + 1) = p; // G
3661  *(pt_output + 2) = p; // B
3662 
3663  pt_input++;
3664  pt_output += 3;
3665  }
3666 }
3667 
3675 void vpImageConvert::BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height,
3676  bool flip)
3677 {
3678  // if we have to flip the image, we start from the end last scanline so the
3679  // step is negative
3680  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
3681 
3682  // starting source address = last line if we need to flip the image
3683  unsigned char *src = (flip) ? (bgr + (width * height * 3) + lineStep) : bgr;
3684 
3685  for (unsigned int i = 0; i < height; i++) {
3686  unsigned char *line = src;
3687  for (unsigned int j = 0; j < width; j++) {
3688  *rgba++ = *(line + 2);
3689  *rgba++ = *(line + 1);
3690  *rgba++ = *(line + 0);
3691  *rgba++ = vpRGBa::alpha_default;
3692 
3693  line += 3;
3694  }
3695  // go to the next line
3696  src += lineStep;
3697  }
3698 }
3699 
3705 void vpImageConvert::BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height,
3706  bool flip)
3707 {
3708  bool checkSSSE3 = vpCPUFeatures::checkSSSE3();
3709 #if !VISP_HAVE_SSSE3
3710  checkSSSE3 = false;
3711 #endif
3712 
3713  if (checkSSSE3) {
3714 #if VISP_HAVE_SSSE3
3715  // Mask to select B component
3716  const __m128i mask_B1 = _mm_set_epi8(-1, -1, -1, -1, 15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1);
3717  const __m128i mask_B2 = _mm_set_epi8(5, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3718  const __m128i mask_B3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1);
3719  const __m128i mask_B4 = _mm_set_epi8(13, -1, 10, -1, 7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1);
3720 
3721  // Mask to select G component
3722  const __m128i mask_G1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 13, -1, 10, -1, 7, -1, 4, -1, 1, -1);
3723  const __m128i mask_G2 = _mm_set_epi8(6, -1, 3, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3724  const __m128i mask_G3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 12, -1, 9, -1);
3725  const __m128i mask_G4 = _mm_set_epi8(14, -1, 11, -1, 8, -1, 5, -1, 2, -1, -1, -1, -1, -1, -1, -1);
3726 
3727  // Mask to select R component
3728  const __m128i mask_R1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1, 5, -1, 2, -1);
3729  const __m128i mask_R2 = _mm_set_epi8(7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3730  const __m128i mask_R3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 10, -1);
3731  const __m128i mask_R4 = _mm_set_epi8(15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1, -1, -1, -1, -1);
3732 
3733  // Mask to select the gray component
3734  const __m128i mask_low1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1);
3735  const __m128i mask_low2 = _mm_set_epi8(15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1);
3736 
3737  // Coefficients RGB to Gray
3738  // const __m128i coeff_R = _mm_set_epi8(
3739  // 54, -1, 54, -1, 54, -1, 54, -1, 54, -1, 54, -1, 54, -1, 54, -1
3740  // );
3741  // const __m128i coeff_G = _mm_set_epi8(
3742  // 183, -1, 183, -1, 183, -1, 183, -1, 183, -1, 183, -1, 183, -1,
3743  // 183, -1
3744  // );
3745  // const __m128i coeff_B = _mm_set_epi8(
3746  // 18, -1, 18, -1, 18, -1, 18, -1, 18, -1, 18, -1, 18, -1, 18, -1
3747  // );
3748  // const __m128i coeff_R = _mm_set_epi16(
3749  // 6969*2, 6969*2, 6969*2, 6969*2, 6969*2, 6969*2, 6969*2, 6969*2
3750  // );
3751  // const __m128i coeff_G = _mm_set_epi16(
3752  // 23434*2, 23434*2, 23434*2, 23434*2, 23434*2, 23434*2, 23434*2,
3753  // 23434*2
3754  // );
3755  // const __m128i coeff_B = _mm_set_epi16(
3756  // 2365*2, 2365*2, 2365*2, 2365*2, 2365*2, 2365*2, 2365*2, 2365*2
3757  // );
3758  const __m128i coeff_R = _mm_set_epi16(13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933);
3759  const __m128i coeff_G = _mm_set_epi16((short int)46871, (short int)46871, (short int)46871, (short int)46871,
3760  (short int)46871, (short int)46871, (short int)46871, (short int)46871);
3761  const __m128i coeff_B = _mm_set_epi16(4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732);
3762 
3763  if (flip) {
3764  int i = ((int)height) - 1;
3765  int lineStep = -(int)(width * 3);
3766  bgr = bgr + (width * (height - 1) * 3);
3767 
3768  unsigned char *linePtr = bgr;
3769  unsigned char r, g, b;
3770 
3771  if (width >= 16) {
3772  for (; i >= 0; i--) {
3773  unsigned int j = 0;
3774 
3775  for (; j <= width - 16; j += 16) {
3776  // Process 16 color pixels
3777  const __m128i data1 = _mm_loadu_si128((const __m128i *)bgr);
3778  const __m128i data2 = _mm_loadu_si128((const __m128i *)(bgr + 16));
3779  const __m128i data3 = _mm_loadu_si128((const __m128i *)(bgr + 32));
3780 
3781  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3782  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3783  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3784 
3785  const __m128i grays_0_7 =
3786  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3787  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3788 
3789  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4));
3790  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4));
3791  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4));
3792 
3793  const __m128i grays_8_15 =
3794  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R), _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G),
3795  _mm_mulhi_epu16(blue_8_15, coeff_B)));
3796 
3797  _mm_storeu_si128((__m128i *)grey, _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1),
3798  _mm_shuffle_epi8(grays_8_15, mask_low2)));
3799 
3800  bgr += 48;
3801  grey += 16;
3802  }
3803 
3804  for (; j < width; j++) {
3805  b = *(bgr++);
3806  g = *(bgr++);
3807  r = *(bgr++);
3808  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
3809  }
3810 
3811  linePtr += lineStep;
3812  bgr = linePtr;
3813  }
3814  }
3815 
3816  for (; i >= 0; i--) {
3817  for (unsigned int j = 0; j < width; j++) {
3818  b = *(bgr++);
3819  g = *(bgr++);
3820  r = *(bgr++);
3821  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
3822  }
3823 
3824  linePtr += lineStep;
3825  bgr = linePtr;
3826  }
3827  } else {
3828  unsigned int i = 0;
3829  unsigned int size = width * height;
3830 
3831  if (size >= 16) {
3832  for (; i <= size - 16; i += 16) {
3833  // Process 16 color pixels
3834  const __m128i data1 = _mm_loadu_si128((const __m128i *)bgr);
3835  const __m128i data2 = _mm_loadu_si128((const __m128i *)(bgr + 16));
3836  const __m128i data3 = _mm_loadu_si128((const __m128i *)(bgr + 32));
3837 
3838  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3839  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3840  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3841 
3842  const __m128i grays_0_7 =
3843  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3844  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3845 
3846  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4));
3847  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4));
3848  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4));
3849 
3850  const __m128i grays_8_15 =
3851  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R),
3852  _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G), _mm_mulhi_epu16(blue_8_15, coeff_B)));
3853 
3854  _mm_storeu_si128((__m128i *)grey, _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1),
3855  _mm_shuffle_epi8(grays_8_15, mask_low2)));
3856 
3857  bgr += 48;
3858  grey += 16;
3859  }
3860  }
3861 
3862  for (; i < size; i++) {
3863  *grey = (unsigned char)(0.2126 * (*(bgr + 2)) + 0.7152 * (*(bgr + 1)) + 0.0722 * (*bgr));
3864 
3865  bgr += 3;
3866  ++grey;
3867  }
3868  }
3869 #endif
3870  } else {
3871  // if we have to flip the image, we start from the end last scanline so
3872  // the step is negative
3873  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
3874 
3875  // starting source address = last line if we need to flip the image
3876  unsigned char *src = (flip) ? bgr + (width * height * 3) + lineStep : bgr;
3877 
3878  for (unsigned int i = 0; i < height; i++) {
3879  unsigned char *line = src;
3880  for (unsigned int j = 0; j < width; j++) {
3881  *grey++ = (unsigned char)(0.2126 * *(line + 2) + 0.7152 * *(line + 1) + 0.0722 * *(line + 0));
3882  line += 3;
3883  }
3884 
3885  // go to the next line
3886  src += lineStep;
3887  }
3888  }
3889 }
3890 
3898 void vpImageConvert::RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int width, unsigned int height,
3899  bool flip)
3900 {
3901  // if we have to flip the image, we start from the end last scanline so the
3902  // step is negative
3903  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
3904 
3905  // starting source address = last line if we need to flip the image
3906  unsigned char *src = (flip) ? (rgb + (width * height * 3) + lineStep) : rgb;
3907 
3908  unsigned int j = 0;
3909  unsigned int i = 0;
3910 
3911  for (i = 0; i < height; i++) {
3912  unsigned char *line = src;
3913  for (j = 0; j < width; j++) {
3914  *rgba++ = *(line++);
3915  *rgba++ = *(line++);
3916  *rgba++ = *(line++);
3917  *rgba++ = vpRGBa::alpha_default;
3918  }
3919  // go to the next line
3920  src += lineStep;
3921  }
3922 }
3923 
3929 void vpImageConvert::RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height,
3930  bool flip)
3931 {
3932  if (flip) {
3933  bool checkSSSE3 = vpCPUFeatures::checkSSSE3();
3934 #if !VISP_HAVE_SSSE3
3935  checkSSSE3 = false;
3936 #endif
3937 
3938  if (checkSSSE3) {
3939 #if VISP_HAVE_SSSE3
3940  int i = ((int)height) - 1;
3941  int lineStep = -(int)(width * 3);
3942  rgb = rgb + (width * (height - 1) * 3);
3943 
3944  unsigned char *linePtr = rgb;
3945  unsigned char r, g, b;
3946 
3947  if (width >= 16) {
3948  // Mask to select R component
3949  const __m128i mask_R1 = _mm_set_epi8(-1, -1, -1, -1, 15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1);
3950  const __m128i mask_R2 = _mm_set_epi8(5, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3951  const __m128i mask_R3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1);
3952  const __m128i mask_R4 = _mm_set_epi8(13, -1, 10, -1, 7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1);
3953 
3954  // Mask to select G component
3955  const __m128i mask_G1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 13, -1, 10, -1, 7, -1, 4, -1, 1, -1);
3956  const __m128i mask_G2 = _mm_set_epi8(6, -1, 3, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3957  const __m128i mask_G3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 12, -1, 9, -1);
3958  const __m128i mask_G4 = _mm_set_epi8(14, -1, 11, -1, 8, -1, 5, -1, 2, -1, -1, -1, -1, -1, -1, -1);
3959 
3960  // Mask to select B component
3961  const __m128i mask_B1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1, 5, -1, 2, -1);
3962  const __m128i mask_B2 = _mm_set_epi8(7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3963  const __m128i mask_B3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 10, -1);
3964  const __m128i mask_B4 = _mm_set_epi8(15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1, -1, -1, -1, -1);
3965 
3966  // Mask to select the gray component
3967  const __m128i mask_low1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1);
3968  const __m128i mask_low2 = _mm_set_epi8(15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1);
3969 
3970  // Coefficients RGB to Gray
3971  const __m128i coeff_R = _mm_set_epi16(13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933);
3972  const __m128i coeff_G = _mm_set_epi16((short int)46871, (short int)46871, (short int)46871, (short int)46871,
3973  (short int)46871, (short int)46871, (short int)46871, (short int)46871);
3974  const __m128i coeff_B = _mm_set_epi16(4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732);
3975 
3976  for (; i >= 0; i--) {
3977  unsigned int j = 0;
3978 
3979  for (; j <= width - 16; j += 16) {
3980  // Process 16 color pixels
3981  const __m128i data1 = _mm_loadu_si128((const __m128i *)rgb);
3982  const __m128i data2 = _mm_loadu_si128((const __m128i *)(rgb + 16));
3983  const __m128i data3 = _mm_loadu_si128((const __m128i *)(rgb + 32));
3984 
3985  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3986  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3987  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3988 
3989  const __m128i grays_0_7 =
3990  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3991  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3992 
3993  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4));
3994  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4));
3995  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4));
3996 
3997  const __m128i grays_8_15 =
3998  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R), _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G),
3999  _mm_mulhi_epu16(blue_8_15, coeff_B)));
4000 
4001  _mm_storeu_si128((__m128i *)grey, _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1),
4002  _mm_shuffle_epi8(grays_8_15, mask_low2)));
4003 
4004  rgb += 48;
4005  grey += 16;
4006  }
4007 
4008  for (; j < width; j++) {
4009  r = *(rgb++);
4010  g = *(rgb++);
4011  b = *(rgb++);
4012  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
4013  }
4014 
4015  linePtr += lineStep;
4016  rgb = linePtr;
4017  }
4018  }
4019 
4020  for (; i >= 0; i--) {
4021  for (unsigned int j = 0; j < width; j++) {
4022  r = *(rgb++);
4023  g = *(rgb++);
4024  b = *(rgb++);
4025  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
4026  }
4027 
4028  linePtr += lineStep;
4029  rgb = linePtr;
4030  }
4031 #endif
4032  } else {
4033  // if we have to flip the image, we start from the end last scanline so
4034  // the step is negative
4035  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
4036 
4037  // starting source address = last line if we need to flip the image
4038  unsigned char *src = (flip) ? rgb + (width * height * 3) + lineStep : rgb;
4039 
4040  unsigned int j = 0;
4041  unsigned int i = 0;
4042 
4043  unsigned r, g, b;
4044 
4045  for (i = 0; i < height; i++) {
4046  unsigned char *line = src;
4047  for (j = 0; j < width; j++) {
4048  r = *(line++);
4049  g = *(line++);
4050  b = *(line++);
4051  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
4052  }
4053 
4054  // go to the next line
4055  src += lineStep;
4056  }
4057  }
4058  } else {
4059  RGBToGrey(rgb, grey, width * height);
4060  }
4061 }
4062 
4066 void vpImageConvert::computeYCbCrLUT()
4067 {
4068  if (YCbCrLUTcomputed == false) {
4069  int index = 256;
4070 
4071  while (index--) {
4072 
4073  int aux = index - 128;
4074  vpImageConvert::vpCrr[index] = (int)(364.6610 * aux) >> 8;
4075  vpImageConvert::vpCgb[index] = (int)(-89.8779 * aux) >> 8;
4076  vpImageConvert::vpCgr[index] = (int)(-185.8154 * aux) >> 8;
4077  vpImageConvert::vpCbb[index] = (int)(460.5724 * aux) >> 8;
4078  }
4079 
4080  YCbCrLUTcomputed = true;
4081  }
4082 }
4083 
4103 void vpImageConvert::YCbCrToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
4104 {
4105  unsigned char *cbv;
4106  unsigned char *crv;
4107  unsigned char *pt_ycbcr = ycbcr;
4108  unsigned char *pt_rgb = rgb;
4109  cbv = pt_ycbcr + 1;
4110  crv = pt_ycbcr + 3;
4111 
4112  vpImageConvert::computeYCbCrLUT();
4113 
4114  int col = 0;
4115 
4116  while (size--) {
4117  int val_r, val_g, val_b;
4118  if (!(col++ % 2)) {
4119  cbv = pt_ycbcr + 1;
4120  crv = pt_ycbcr + 3;
4121  }
4122 
4123  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4124  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4125  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4126 
4127  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4128 
4129  *pt_rgb++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4130  *pt_rgb++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4131  *pt_rgb++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4132 
4133  pt_ycbcr += 2;
4134  }
4135 }
4136 
4160 void vpImageConvert::YCbCrToRGBa(unsigned char *ycbcr, unsigned char *rgba, unsigned int size)
4161 {
4162  unsigned char *cbv;
4163  unsigned char *crv;
4164  unsigned char *pt_ycbcr = ycbcr;
4165  unsigned char *pt_rgba = rgba;
4166  cbv = pt_ycbcr + 1;
4167  crv = pt_ycbcr + 3;
4168 
4169  vpImageConvert::computeYCbCrLUT();
4170 
4171  int col = 0;
4172 
4173  while (size--) {
4174  int val_r, val_g, val_b;
4175  if (!(col++ % 2)) {
4176  cbv = pt_ycbcr + 1;
4177  crv = pt_ycbcr + 3;
4178  }
4179 
4180  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4181  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4182  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4183 
4184  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4185 
4186  *pt_rgba++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4187  *pt_rgba++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4188  *pt_rgba++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4189  *pt_rgba++ = vpRGBa::alpha_default;
4190 
4191  pt_ycbcr += 2;
4192  }
4193 }
4194 
4211 void vpImageConvert::YCbCrToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
4212 {
4213  unsigned int i = 0, j = 0;
4214 
4215  while (j < size * 2) {
4216  grey[i++] = yuv[j];
4217  grey[i++] = yuv[j + 2];
4218  j += 4;
4219  }
4220 }
4221 
4240 void vpImageConvert::YCrCbToRGB(unsigned char *ycrcb, unsigned char *rgb, unsigned int size)
4241 {
4242  unsigned char *cbv;
4243  unsigned char *crv;
4244  unsigned char *pt_ycbcr = ycrcb;
4245  unsigned char *pt_rgb = rgb;
4246  crv = pt_ycbcr + 1;
4247  cbv = pt_ycbcr + 3;
4248 
4249  vpImageConvert::computeYCbCrLUT();
4250 
4251  int col = 0;
4252 
4253  while (size--) {
4254  int val_r, val_g, val_b;
4255  if (!(col++ % 2)) {
4256  crv = pt_ycbcr + 1;
4257  cbv = pt_ycbcr + 3;
4258  }
4259 
4260  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4261  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4262  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4263 
4264  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4265 
4266  *pt_rgb++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4267  *pt_rgb++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4268  *pt_rgb++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4269 
4270  pt_ycbcr += 2;
4271  }
4272 }
4295 void vpImageConvert::YCrCbToRGBa(unsigned char *ycrcb, unsigned char *rgba, unsigned int size)
4296 {
4297  unsigned char *cbv;
4298  unsigned char *crv;
4299  unsigned char *pt_ycbcr = ycrcb;
4300  unsigned char *pt_rgba = rgba;
4301  crv = pt_ycbcr + 1;
4302  cbv = pt_ycbcr + 3;
4303 
4304  vpImageConvert::computeYCbCrLUT();
4305 
4306  int col = 0;
4307 
4308  while (size--) {
4309  int val_r, val_g, val_b;
4310  if (!(col++ % 2)) {
4311  crv = pt_ycbcr + 1;
4312  cbv = pt_ycbcr + 3;
4313  }
4314 
4315  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4316  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4317  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4318 
4319  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4320 
4321  *pt_rgba++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4322  *pt_rgba++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4323  *pt_rgba++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4324  *pt_rgba++ = vpRGBa::alpha_default;
4325 
4326  pt_ycbcr += 2;
4327  }
4328 }
4329 
4367 {
4368  size_t n = src.getNumberOfPixel();
4369  unsigned int height = src.getHeight();
4370  unsigned int width = src.getWidth();
4371  unsigned char *input;
4372  unsigned char *dst;
4373 
4374  vpImage<unsigned char> *tabChannel[4];
4375 
4376  /* incrsrc[0] = 0; //init
4377  incrsrc[1] = 0; //step after the first used channel
4378  incrsrc[2] = 0; //step after the second used channel
4379  incrsrc[3] = 0;
4380  incrsrc[4] = 0;
4381  */
4382  tabChannel[0] = pR;
4383  tabChannel[1] = pG;
4384  tabChannel[2] = pB;
4385  tabChannel[3] = pa;
4386 
4387  size_t i; /* ordre */
4388  for (unsigned int j = 0; j < 4; j++) {
4389  if (tabChannel[j] != NULL) {
4390  if (tabChannel[j]->getHeight() != height || tabChannel[j]->getWidth() != width) {
4391  tabChannel[j]->resize(height, width);
4392  }
4393  dst = (unsigned char *)tabChannel[j]->bitmap;
4394 
4395  input = (unsigned char *)src.bitmap + j;
4396  i = 0;
4397 #if 1 // optimization
4398  if (n >= 4) { /* boucle deroulee lsize fois */
4399  n -= 3;
4400  for (; i < n; i += 4) {
4401  *dst = *input;
4402  input += 4;
4403  dst++;
4404  *dst = *input;
4405  input += 4;
4406  dst++;
4407  *dst = *input;
4408  input += 4;
4409  dst++;
4410  *dst = *input;
4411  input += 4;
4412  dst++;
4413  }
4414  n += 3;
4415  }
4416 #endif
4417  for (; i < n; i++) {
4418  *dst = *input;
4419  input += 4;
4420  dst++;
4421  }
4422  }
4423  }
4424 }
4425 
4436 {
4437  // Check if the input channels have all the same dimensions
4438  std::map<unsigned int, unsigned int> mapOfWidths, mapOfHeights;
4439  if (R != NULL) {
4440  mapOfWidths[R->getWidth()]++;
4441  mapOfHeights[R->getHeight()]++;
4442  }
4443 
4444  if (G != NULL) {
4445  mapOfWidths[G->getWidth()]++;
4446  mapOfHeights[G->getHeight()]++;
4447  }
4448 
4449  if (B != NULL) {
4450  mapOfWidths[B->getWidth()]++;
4451  mapOfHeights[B->getHeight()]++;
4452  }
4453 
4454  if (a != NULL) {
4455  mapOfWidths[a->getWidth()]++;
4456  mapOfHeights[a->getHeight()]++;
4457  }
4458 
4459  if (mapOfWidths.size() == 1 && mapOfHeights.size() == 1) {
4460  unsigned int width = mapOfWidths.begin()->first;
4461  unsigned int height = mapOfHeights.begin()->first;
4462 
4463  RGBa.resize(height, width);
4464 
4465  unsigned int size = width * height;
4466  for (unsigned int i = 0; i < size; i++) {
4467  if (R != NULL) {
4468  RGBa.bitmap[i].R = R->bitmap[i];
4469  }
4470 
4471  if (G != NULL) {
4472  RGBa.bitmap[i].G = G->bitmap[i];
4473  }
4474 
4475  if (B != NULL) {
4476  RGBa.bitmap[i].B = B->bitmap[i];
4477  }
4478 
4479  if (a != NULL) {
4480  RGBa.bitmap[i].A = a->bitmap[i];
4481  }
4482  }
4483  } else {
4484  throw vpException(vpException::dimensionError, "Mismatch dimensions !");
4485  }
4486 }
4487 
4498 void vpImageConvert::MONO16ToGrey(unsigned char *grey16, unsigned char *grey, unsigned int size)
4499 {
4500  int i = (((int)size) << 1) - 1;
4501  int j = (int)size - 1;
4502 
4503  while (i >= 0) {
4504  int y = grey16[i--];
4505  grey[j--] = static_cast<unsigned char>((y + (grey16[i--] << 8)) >> 8);
4506  }
4507 }
4508 
4521 void vpImageConvert::MONO16ToRGBa(unsigned char *grey16, unsigned char *rgba, unsigned int size)
4522 {
4523  int i = (((int)size) << 1) - 1;
4524  int j = (int)(size * 4 - 1);
4525 
4526  while (i >= 0) {
4527  int y = grey16[i--];
4528  unsigned char v = static_cast<unsigned char>((y + (grey16[i--] << 8)) >> 8);
4529  rgba[j--] = vpRGBa::alpha_default;
4530  rgba[j--] = v;
4531  rgba[j--] = v;
4532  rgba[j--] = v;
4533  }
4534 }
4535 
4536 void vpImageConvert::HSV2RGB(const double *hue_, const double *saturation_, const double *value_, unsigned char *rgb,
4537  const unsigned int size, const unsigned int step)
4538 {
4539  for (unsigned int i = 0; i < size; i++) {
4540  double hue = hue_[i], saturation = saturation_[i], value = value_[i];
4541 
4542  if (vpMath::equal(saturation, 0.0, std::numeric_limits<double>::epsilon())) {
4543  hue = value;
4544  saturation = value;
4545  } else {
4546  double h = hue * 6.0;
4547  double s = saturation;
4548  double v = value;
4549 
4550  if (vpMath::equal(h, 6.0, std::numeric_limits<double>::epsilon())) {
4551  h = 0.0;
4552  }
4553 
4554  double f = h - (int)h;
4555  double p = v * (1.0 - s);
4556  double q = v * (1.0 - s * f);
4557  double t = v * (1.0 - s * (1.0 - f));
4558 
4559  switch ((int)h) {
4560  case 0:
4561  hue = v;
4562  saturation = t;
4563  value = p;
4564  break;
4565 
4566  case 1:
4567  hue = q;
4568  saturation = v;
4569  value = p;
4570  break;
4571 
4572  case 2:
4573  hue = p;
4574  saturation = v;
4575  value = t;
4576  break;
4577 
4578  case 3:
4579  hue = p;
4580  saturation = q;
4581  value = v;
4582  break;
4583 
4584  case 4:
4585  hue = t;
4586  saturation = p;
4587  value = v;
4588  break;
4589 
4590  default: // case 5:
4591  hue = v;
4592  saturation = p;
4593  value = q;
4594  break;
4595  }
4596  }
4597 
4598  rgb[i * step] = (unsigned char)vpMath::round(hue * 255.0);
4599  rgb[i * step + 1] = (unsigned char)vpMath::round(saturation * 255.0);
4600  rgb[i * step + 2] = (unsigned char)vpMath::round(value * 255.0);
4601  if (step == 4) // alpha
4602  rgb[i * step + 3] = vpRGBa::alpha_default;
4603  }
4604 }
4605 
4606 void vpImageConvert::RGB2HSV(const unsigned char *rgb, double *hue, double *saturation, double *value,
4607  const unsigned int size, const unsigned int step)
4608 {
4609  for (unsigned int i = 0; i < size; i++) {
4610  double red, green, blue;
4611  double h, s, v;
4612  double min, max;
4613 
4614  red = rgb[i * step] / 255.0;
4615  green = rgb[i * step + 1] / 255.0;
4616  blue = rgb[i * step + 2] / 255.0;
4617 
4618  if (red > green) {
4619  max = ((std::max))(red, blue);
4620  min = ((std::min))(green, blue);
4621  } else {
4622  max = ((std::max))(green, blue);
4623  min = ((std::min))(red, blue);
4624  }
4625 
4626  v = max;
4627 
4628  if (!vpMath::equal(max, 0.0, std::numeric_limits<double>::epsilon())) {
4629  s = (max - min) / max;
4630  } else {
4631  s = 0.0;
4632  }
4633 
4634  if (vpMath::equal(s, 0.0, std::numeric_limits<double>::epsilon())) {
4635  h = 0.0;
4636  } else {
4637  double delta = max - min;
4638  if (vpMath::equal(delta, 0.0, std::numeric_limits<double>::epsilon())) {
4639  delta = 1.0;
4640  }
4641 
4642  if (vpMath::equal(red, max, std::numeric_limits<double>::epsilon())) {
4643  h = (green - blue) / delta;
4644  } else if (vpMath::equal(green, max, std::numeric_limits<double>::epsilon())) {
4645  h = 2 + (blue - red) / delta;
4646  } else {
4647  h = 4 + (red - green) / delta;
4648  }
4649 
4650  h /= 6.0;
4651  if (h < 0.0) {
4652  h += 1.0;
4653  } else if (h > 1.0) {
4654  h -= 1.0;
4655  }
4656  }
4657 
4658  hue[i] = h;
4659  saturation[i] = s;
4660  value[i] = v;
4661  }
4662 }
4663 
4676 void vpImageConvert::HSVToRGBa(const double *hue, const double *saturation, const double *value, unsigned char *rgba,
4677  const unsigned int size)
4678 {
4679  vpImageConvert::HSV2RGB(hue, saturation, value, rgba, size, 4);
4680 }
4681 
4694 void vpImageConvert::HSVToRGBa(const unsigned char *hue, const unsigned char *saturation, const unsigned char *value,
4695  unsigned char *rgba, const unsigned int size)
4696 {
4697  for (unsigned int i = 0; i < size; i++) {
4698  double h = hue[i] / 255.0, s = saturation[i] / 255.0, v = value[i] / 255.0;
4699 
4700  vpImageConvert::HSVToRGBa(&h, &s, &v, (rgba + i * 4), 1);
4701  }
4702 }
4703 
4715 void vpImageConvert::RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value,
4716  const unsigned int size)
4717 {
4718  vpImageConvert::RGB2HSV(rgba, hue, saturation, value, size, 4);
4719 }
4720 
4732 void vpImageConvert::RGBaToHSV(const unsigned char *rgba, unsigned char *hue, unsigned char *saturation,
4733  unsigned char *value, const unsigned int size)
4734 {
4735  for (unsigned int i = 0; i < size; i++) {
4736  double h, s, v;
4737  vpImageConvert::RGBaToHSV((rgba + i * 4), &h, &s, &v, 1);
4738 
4739  hue[i] = (unsigned char)(255.0 * h);
4740  saturation[i] = (unsigned char)(255.0 * s);
4741  value[i] = (unsigned char)(255.0 * v);
4742  }
4743 }
4744 
4754 void vpImageConvert::HSVToRGB(const double *hue, const double *saturation, const double *value, unsigned char *rgb,
4755  const unsigned int size)
4756 {
4757  vpImageConvert::HSV2RGB(hue, saturation, value, rgb, size, 3);
4758 }
4759 
4769 void vpImageConvert::HSVToRGB(const unsigned char *hue, const unsigned char *saturation, const unsigned char *value,
4770  unsigned char *rgb, const unsigned int size)
4771 {
4772  for (unsigned int i = 0; i < size; i++) {
4773  double h = hue[i] / 255.0, s = saturation[i] / 255.0, v = value[i] / 255.0;
4774 
4775  vpImageConvert::HSVToRGB(&h, &s, &v, (rgb + i * 3), 1);
4776  }
4777 }
4778 
4789 void vpImageConvert::RGBToHSV(const unsigned char *rgb, double *hue, double *saturation, double *value,
4790  const unsigned int size)
4791 {
4792  vpImageConvert::RGB2HSV(rgb, hue, saturation, value, size, 3);
4793 }
4794 
4805 void vpImageConvert::RGBToHSV(const unsigned char *rgb, unsigned char *hue, unsigned char *saturation,
4806  unsigned char *value, const unsigned int size)
4807 {
4808  for (unsigned int i = 0; i < size; i++) {
4809  double h, s, v;
4810 
4811  vpImageConvert::RGBToHSV((rgb + i * 3), &h, &s, &v, 1);
4812 
4813  hue[i] = (unsigned char)(255.0 * h);
4814  saturation[i] = (unsigned char)(255.0 * s);
4815  value[i] = (unsigned char)(255.0 * v);
4816  }
4817 }
unsigned int getCols() const
Definition: vpImage.h:177
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:244
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:1017
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:141
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:296
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:241
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:216
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:225
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:207
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:879
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:186
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)