Visual Servoing Platform  version 3.3.1 under development (2020-05-29)
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  unsigned char f = static_cast<unsigned char>(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
306 void vpImageConvert::convert(const IplImage *src, vpImage<vpRGBa> &dest, bool flip)
307 {
308  int nChannel = src->nChannels;
309  int depth = src->depth;
310  int height = src->height;
311  int width = src->width;
312  int widthStep = src->widthStep;
313  int lineStep = (flip) ? 1 : 0;
314 
315  if (nChannel == 3 && depth == 8) {
316  dest.resize((unsigned int)height, (unsigned int)width);
317 
318  // starting source address
319  unsigned char *input = (unsigned char *)src->imageData;
320  unsigned char *beginOutput = (unsigned char *)dest.bitmap;
321 
322  for (int i = 0; i < height; i++) {
323  unsigned char *line = input;
324  unsigned char *output = beginOutput + lineStep * (4 * width * (height - 1 - i)) + (1 - lineStep) * 4 * width * i;
325  for (int j = 0; j < width; j++) {
326  *(output++) = *(line + 2);
327  *(output++) = *(line + 1);
328  *(output++) = *(line);
329  *(output++) = vpRGBa::alpha_default;
330 
331  line += 3;
332  }
333  // go to the next line
334  input += widthStep;
335  }
336  } else if (nChannel == 1 && depth == 8) {
337  dest.resize((unsigned int)height, (unsigned int)width);
338  // starting source address
339  unsigned char *input = (unsigned char *)src->imageData;
340  unsigned char *beginOutput = (unsigned char *)dest.bitmap;
341 
342  for (int i = 0; i < height; i++) {
343  unsigned char *line = input;
344  unsigned char *output = beginOutput + lineStep * (4 * width * (height - 1 - i)) + (1 - lineStep) * 4 * width * i;
345  for (int j = 0; j < width; j++) {
346  *output++ = *(line);
347  *output++ = *(line);
348  *output++ = *(line);
349  *output++ = vpRGBa::alpha_default; // alpha
350 
351  line++;
352  }
353  // go to the next line
354  input += widthStep;
355  }
356  }
357 }
358 
401 void vpImageConvert::convert(const IplImage *src, vpImage<unsigned char> &dest, bool flip)
402 {
403  int nChannel = src->nChannels;
404  int depth = src->depth;
405  int height = src->height;
406  int width = src->width;
407  int widthStep = src->widthStep;
408  int lineStep = (flip) ? 1 : 0;
409 
410  if (flip == false) {
411  if (widthStep == width) {
412  if (nChannel == 1 && depth == 8) {
413  dest.resize((unsigned int)height, (unsigned int)width);
414  memcpy(dest.bitmap, src->imageData, (size_t)(height * width));
415  }
416  if (nChannel == 3 && depth == 8) {
417  dest.resize((unsigned int)height, (unsigned int)width);
418  BGRToGrey((unsigned char *)src->imageData, dest.bitmap, (unsigned int)width, (unsigned int)height, false);
419  }
420  } else {
421  if (nChannel == 1 && depth == 8) {
422  dest.resize((unsigned int)height, (unsigned int)width);
423  for (int i = 0; i < height; i++) {
424  memcpy(dest.bitmap + i * width, src->imageData + i * widthStep, (size_t)width);
425  }
426  }
427  if (nChannel == 3 && depth == 8) {
428  dest.resize((unsigned int)height, (unsigned int)width);
429  for (int i = 0; i < height; i++) {
430  BGRToGrey((unsigned char *)src->imageData + i * widthStep, dest.bitmap + i * width, (unsigned int)width, 1,
431  false);
432  }
433  }
434  }
435  } else {
436  if (nChannel == 1 && depth == 8) {
437  dest.resize((unsigned int)height, (unsigned int)width);
438  unsigned char *beginOutput = (unsigned char *)dest.bitmap;
439  for (int i = 0; i < height; i++) {
440  memcpy(beginOutput + lineStep * (4 * width * (height - 1 - i)), src->imageData + i * widthStep, (size_t)width);
441  }
442  }
443  if (nChannel == 3 && depth == 8) {
444  dest.resize((unsigned int)height, (unsigned int)width);
445  // for (int i = 0 ; i < height ; i++){
446  BGRToGrey((unsigned char *)src->imageData /*+ i*widthStep*/, dest.bitmap /*+ i*width*/, (unsigned int)width,
447  (unsigned int)height /*1*/, true);
448  //}
449  }
450  }
451 }
452 
496 void vpImageConvert::convert(const vpImage<vpRGBa> &src, IplImage *&dest)
497 {
498  int height = (int)src.getHeight();
499  int width = (int)src.getWidth();
500  CvSize size = cvSize(width, height);
501  int depth = 8;
502  int channels = 3;
503  if (dest != NULL) {
504  if (dest->nChannels != channels || dest->depth != depth || dest->height != height || dest->width != width) {
505  if (dest->nChannels != 0)
506  cvReleaseImage(&dest);
507  dest = cvCreateImage(size, depth, channels);
508  }
509  } else
510  dest = cvCreateImage(size, depth, channels);
511 
512  // starting source address
513  unsigned char *input = (unsigned char *)src.bitmap; // rgba image
514  unsigned char *output = (unsigned char *)dest->imageData; // bgr image
515 
516  int j = 0;
517  int i = 0;
518  int widthStep = dest->widthStep;
519 
520  for (i = 0; i < height; i++) {
521  output = (unsigned char *)dest->imageData + i * widthStep;
522  unsigned char *line = input;
523  for (j = 0; j < width; j++) {
524  *output++ = *(line + 2); // B
525  *output++ = *(line + 1); // G
526  *output++ = *(line); // R
527 
528  line += 4;
529  }
530  // go to the next line
531  input += 4 * width;
532  }
533 }
534 
578 void vpImageConvert::convert(const vpImage<unsigned char> &src, IplImage *&dest)
579 {
580  unsigned int height = src.getHeight();
581  unsigned int width = src.getWidth();
582  CvSize size = cvSize((int)width, (int)height);
583  int depth = 8;
584  int channels = 1;
585  if (dest != NULL) {
586  if (dest->nChannels != channels || dest->depth != depth || dest->height != (int)height ||
587  dest->width != (int)width) {
588  if (dest->nChannels != 0)
589  cvReleaseImage(&dest);
590  dest = cvCreateImage(size, depth, channels);
591  }
592  } else
593  dest = cvCreateImage(size, depth, channels);
594 
595  unsigned int widthStep = (unsigned int)dest->widthStep;
596 
597  if (width == widthStep) {
598  memcpy(dest->imageData, src.bitmap, width * height);
599  } else {
600  // copying each line taking account of the widthStep
601  for (unsigned int i = 0; i < height; i++) {
602  memcpy(dest->imageData + i * widthStep, src.bitmap + i * width, width);
603  }
604  }
605 }
606 
607 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
608 
655 void vpImageConvert::convert(const cv::Mat &src, vpImage<vpRGBa> &dest, bool flip)
656 {
657  if (src.type() == CV_8UC4) {
658  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
659  vpRGBa rgbaVal;
660  for (unsigned int i = 0; i < dest.getRows(); ++i)
661  for (unsigned int j = 0; j < dest.getCols(); ++j) {
662  cv::Vec4b tmp = src.at<cv::Vec4b>((int)i, (int)j);
663  rgbaVal.R = tmp[2];
664  rgbaVal.G = tmp[1];
665  rgbaVal.B = tmp[0];
666  rgbaVal.A = tmp[3];
667  if (flip)
668  dest[dest.getRows() - i - 1][j] = rgbaVal;
669  else
670  dest[i][j] = rgbaVal;
671  }
672  } else if (src.type() == CV_8UC3) {
673  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
674 
675  bool checkSSSE3 = vpCPUFeatures::checkSSSE3();
676  #if !VISP_HAVE_SSSE3
677  checkSSSE3 = false;
678  #endif
679 
680  if (checkSSSE3 && src.isContinuous() && !flip) {
681 #if VISP_HAVE_SSSE3
682  int i = 0;
683  int size = src.rows*src.cols;
684  const uchar* bgr = src.ptr<uchar>();
685  unsigned char* rgba = (unsigned char*) dest.bitmap;
686 
687  if (size >= 16) {
688  // Mask to reorder BGR to RGBa
689  const __m128i mask_1 = _mm_set_epi8(-1, 9, 10, 11, -1, 6, 7, 8, -1, 3, 4, 5, -1, 0, 1, 2);
690  const __m128i mask_2 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, 12, 13, 14);
691  const __m128i mask_3 = _mm_set_epi8(-1, 5, 6, 7, -1, 2, 3, 4, -1, -1, 0, 1, -1, -1, -1, -1);
692  const __m128i mask_4 = _mm_set_epi8(-1, -1, -1, -1, -1, 14, 15, -1, -1, 11, 12, 13, -1, 8, 9, 10);
693  const __m128i mask_5 = _mm_set_epi8(-1, 1, 2, 3, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1);
694  const __m128i mask_6 = _mm_set_epi8(-1, 13, 14, 15, -1, 10, 11, 12, -1, 7, 8, 9, -1, 4, 5, 6);
695 
696  __m128i res[4];
697  int size_vec = size - 16;
698  // Note: size_vec introduced to avoid warning: assuming signed overflow does not occur
699  // when simplifying range test [-Wstrict-overflow]
700  for (; i <= size_vec; i += 16) {
701  // Process 16 BGR color pixels
702  const __m128i data1 = _mm_loadu_si128((const __m128i *)bgr);
703  const __m128i data2 = _mm_loadu_si128((const __m128i *)(bgr + 16));
704  const __m128i data3 = _mm_loadu_si128((const __m128i *)(bgr + 32));
705 
706  res[0] = _mm_shuffle_epi8(data1, mask_1);
707  res[1] = _mm_or_si128(_mm_shuffle_epi8(data1, mask_2), _mm_shuffle_epi8(data2, mask_3));
708  res[2] = _mm_or_si128(_mm_shuffle_epi8(data2, mask_4), _mm_shuffle_epi8(data3, mask_5));
709  res[3] = _mm_shuffle_epi8(data3, mask_6);
710 
711  _mm_storeu_si128((__m128i *)rgba, res[0]);
712  _mm_storeu_si128((__m128i *)(rgba+16), res[1]);
713  _mm_storeu_si128((__m128i *)(rgba+32), res[2]);
714  _mm_storeu_si128((__m128i *)(rgba+48), res[3]);
715 
716  bgr += 48;
717  rgba += 64;
718  }
719  }
720 
721  for (; i < size; i++) {
722  *rgba = *(bgr+2); rgba++;
723  *rgba = *(bgr+1); rgba++;
724  *rgba = *(bgr); rgba++;
725  *rgba = 0; rgba++;
726 
727  bgr += 3;
728  }
729 #endif
730  } else {
731  vpRGBa rgbaVal;
732  rgbaVal.A = vpRGBa::alpha_default;
733  for (unsigned int i = 0; i < dest.getRows(); ++i) {
734  for (unsigned int j = 0; j < dest.getCols(); ++j) {
735  cv::Vec3b tmp = src.at<cv::Vec3b>((int)i, (int)j);
736  rgbaVal.R = tmp[2];
737  rgbaVal.G = tmp[1];
738  rgbaVal.B = tmp[0];
739  if (flip) {
740  dest[dest.getRows() - i - 1][j] = rgbaVal;
741  } else {
742  dest[i][j] = rgbaVal;
743  }
744  }
745  }
746  }
747  } else if (src.type() == CV_8UC1) {
748  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
749  vpRGBa rgbaVal;
750  for (unsigned int i = 0; i < dest.getRows(); ++i) {
751  for (unsigned int j = 0; j < dest.getCols(); ++j) {
752  rgbaVal = src.at<unsigned char>((int)i, (int)j);
753  if (flip) {
754  dest[dest.getRows() - i - 1][j] = rgbaVal;
755  } else {
756  dest[i][j] = rgbaVal;
757  }
758  }
759  }
760  }
761 }
762 
804 void vpImageConvert::convert(const cv::Mat &src, vpImage<unsigned char> &dest, bool flip)
805 {
806  if (src.type() == CV_8UC1) {
807  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
808  if (src.isContinuous() && !flip) {
809  memcpy(dest.bitmap, src.data, (size_t)(src.rows * src.cols));
810  } else {
811  if (flip) {
812  for (unsigned int i = 0; i < dest.getRows(); ++i) {
813  memcpy(dest.bitmap + i * dest.getCols(), src.data + (dest.getRows() - i - 1) * src.step1(), (size_t)src.step);
814  }
815  } else {
816  for (unsigned int i = 0; i < dest.getRows(); ++i) {
817  memcpy(dest.bitmap + i * dest.getCols(), src.data + i * src.step1(), (size_t)src.step);
818  }
819  }
820  }
821  } else if (src.type() == CV_8UC3) {
822  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
823  if (src.isContinuous() /*&& !flip*/) {
824  BGRToGrey((unsigned char *)src.data, (unsigned char *)dest.bitmap, (unsigned int)src.cols, (unsigned int)src.rows,
825  flip);
826  } else {
827  if (flip) {
828  for (unsigned int i = 0; i < dest.getRows(); ++i) {
829  BGRToGrey((unsigned char *)src.data + i * src.step1(),
830  (unsigned char *)dest.bitmap + (dest.getRows() - i - 1) * dest.getCols(),
831  (unsigned int)dest.getCols(), 1, false);
832  }
833  } else {
834  for (unsigned int i = 0; i < dest.getRows(); ++i) {
835  BGRToGrey((unsigned char *)src.data + i * src.step1(), (unsigned char *)dest.bitmap + i * dest.getCols(),
836  (unsigned int)dest.getCols(), 1, false);
837  }
838  }
839  }
840  }
841 }
842 
879 void vpImageConvert::convert(const vpImage<vpRGBa> &src, cv::Mat &dest)
880 {
881  cv::Mat vpToMat((int)src.getRows(), (int)src.getCols(), CV_8UC4, (void *)src.bitmap);
882  cv::cvtColor(vpToMat, dest, cv::COLOR_RGBA2BGR);
883 }
884 
923 void vpImageConvert::convert(const vpImage<unsigned char> &src, cv::Mat &dest, bool copyData)
924 {
925  if (copyData) {
926  cv::Mat tmpMap((int)src.getRows(), (int)src.getCols(), CV_8UC1, (void *)src.bitmap);
927  dest = tmpMap.clone();
928  } else {
929  dest = cv::Mat((int)src.getRows(), (int)src.getCols(), CV_8UC1, (void *)src.bitmap);
930  }
931 }
932 
933 #endif
934 #endif
935 
936 #ifdef VISP_HAVE_YARP
937 
971 void vpImageConvert::convert(const vpImage<unsigned char> &src, yarp::sig::ImageOf<yarp::sig::PixelMono> *dest,
972  bool copyData)
973 {
974  if (copyData) {
975  dest->resize(src.getWidth(), src.getHeight());
976  memcpy(dest->getRawImage(), src.bitmap, src.getHeight() * src.getWidth());
977  } else
978  dest->setExternal(src.bitmap, (int)src.getCols(), (int)src.getRows());
979 }
980 
1019 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelMono> *src, vpImage<unsigned char> &dest,
1020  bool copyData)
1021 {
1022  dest.resize(src->height(), src->width());
1023  if (copyData)
1024  memcpy(dest.bitmap, src->getRawImage(), src->height() * src->width() * sizeof(yarp::sig::PixelMono));
1025  else
1026  dest.bitmap = src->getRawImage();
1027 }
1028 
1063 void vpImageConvert::convert(const vpImage<vpRGBa> &src, yarp::sig::ImageOf<yarp::sig::PixelRgba> *dest,
1064  bool copyData)
1065 {
1066  if (copyData) {
1067  dest->resize(src.getWidth(), src.getHeight());
1068  memcpy(dest->getRawImage(), src.bitmap, src.getHeight() * src.getWidth() * sizeof(vpRGBa));
1069  } else
1070  dest->setExternal(src.bitmap, (int)src.getCols(), (int)src.getRows());
1071 }
1072 
1111 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelRgba> *src, vpImage<vpRGBa> &dest,
1112  bool copyData)
1113 {
1114  dest.resize(src->height(), src->width());
1115  if (copyData)
1116  memcpy(dest.bitmap, src->getRawImage(), src->height() * src->width() * sizeof(yarp::sig::PixelRgba));
1117  else
1118  dest.bitmap = static_cast<vpRGBa *>(src->getRawImage());
1119 }
1120 
1153 void vpImageConvert::convert(const vpImage<vpRGBa> &src, yarp::sig::ImageOf<yarp::sig::PixelRgb> *dest)
1154 {
1155  dest->resize(src.getWidth(), src.getHeight());
1156  for (unsigned int i = 0; i < src.getRows(); i++) {
1157  for (unsigned int j = 0; j < src.getWidth(); j++) {
1158  dest->pixel(j, i).r = src[i][j].R;
1159  dest->pixel(j, i).g = src[i][j].G;
1160  dest->pixel(j, i).b = src[i][j].B;
1161  }
1162  }
1163 }
1164 
1203 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelRgb> *src, vpImage<vpRGBa> &dest)
1204 {
1205  dest.resize(src->height(), src->width());
1206  for (int i = 0; i < src->height(); i++) {
1207  for (int j = 0; j < src->width(); j++) {
1208  dest[i][j].R = src->pixel(j, i).r;
1209  dest[i][j].G = src->pixel(j, i).g;
1210  dest[i][j].B = src->pixel(j, i).b;
1211  dest[i][j].A = vpRGBa::alpha_default;
1212  }
1213  }
1214 }
1215 
1216 #endif
1217 
1218 #define vpSAT(c) \
1219  if (c & (~255)) { \
1220  if (c < 0) \
1221  c = 0; \
1222  else \
1223  c = 255; \
1224  }
1225 
1233 void vpImageConvert::YUYVToRGBa(unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height)
1234 {
1235  unsigned char *s;
1236  unsigned char *d;
1237  int w, h;
1238  int r, g, b, cr, cg, cb, y1, y2;
1239 
1240  h = (int)height;
1241  w = (int)width;
1242  s = yuyv;
1243  d = rgba;
1244  while (h--) {
1245  int c = w >> 1;
1246  while (c--) {
1247  y1 = *s++;
1248  cb = ((*s - 128) * 454) >> 8;
1249  cg = (*s++ - 128) * 88;
1250  y2 = *s++;
1251  cr = ((*s - 128) * 359) >> 8;
1252  cg = (cg + (*s++ - 128) * 183) >> 8;
1253 
1254  r = y1 + cr;
1255  b = y1 + cb;
1256  g = y1 - cg;
1257  vpSAT(r);
1258  vpSAT(g);
1259  vpSAT(b);
1260 
1261  *d++ = static_cast<unsigned char>(r);
1262  *d++ = static_cast<unsigned char>(g);
1263  *d++ = static_cast<unsigned char>(b);
1264  *d++ = vpRGBa::alpha_default;
1265 
1266  r = y2 + cr;
1267  b = y2 + cb;
1268  g = y2 - 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  }
1279 }
1280 
1288 void vpImageConvert::YUYVToRGB(unsigned char *yuyv, unsigned char *rgb, unsigned int width, unsigned int height)
1289 {
1290  unsigned char *s;
1291  unsigned char *d;
1292  int h, w;
1293  int r, g, b, cr, cg, cb, y1, y2;
1294 
1295  h = (int)height;
1296  w = (int)width;
1297  s = yuyv;
1298  d = rgb;
1299  while (h--) {
1300  int c = w >> 1;
1301  while (c--) {
1302  y1 = *s++;
1303  cb = ((*s - 128) * 454) >> 8;
1304  cg = (*s++ - 128) * 88;
1305  y2 = *s++;
1306  cr = ((*s - 128) * 359) >> 8;
1307  cg = (cg + (*s++ - 128) * 183) >> 8;
1308 
1309  r = y1 + cr;
1310  b = y1 + cb;
1311  g = y1 - cg;
1312  vpSAT(r);
1313  vpSAT(g);
1314  vpSAT(b);
1315 
1316  *d++ = static_cast<unsigned char>(r);
1317  *d++ = static_cast<unsigned char>(g);
1318  *d++ = static_cast<unsigned char>(b);
1319 
1320  r = y2 + cr;
1321  b = y2 + cb;
1322  g = y2 - cg;
1323  vpSAT(r);
1324  vpSAT(g);
1325  vpSAT(b);
1326 
1327  *d++ = static_cast<unsigned char>(r);
1328  *d++ = static_cast<unsigned char>(g);
1329  *d++ = static_cast<unsigned char>(b);
1330  }
1331  }
1332 }
1340 void vpImageConvert::YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
1341 {
1342  unsigned int i = 0, j = 0;
1343 
1344  while (j < size * 2) {
1345  grey[i++] = yuyv[j];
1346  grey[i++] = yuyv[j + 2];
1347  j += 4;
1348  }
1349 }
1350 
1357 void vpImageConvert::YUV411ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
1358 {
1359 #if 1
1360  // std::cout << "call optimized ConvertYUV411ToRGBa()" << std::endl;
1361  for (unsigned int i = size / 4; i; i--) {
1362  int U = (int)((*yuv++ - 128) * 0.354);
1363  int U5 = 5 * U;
1364  int Y0 = *yuv++;
1365  int Y1 = *yuv++;
1366  int V = (int)((*yuv++ - 128) * 0.707);
1367  int V2 = 2 * V;
1368  int Y2 = *yuv++;
1369  int Y3 = *yuv++;
1370  int UV = -U - V;
1371 
1372  // Original equations
1373  // R = Y + 1.402 V
1374  // G = Y - 0.344 U - 0.714 V
1375  // B = Y + 1.772 U
1376  int R = Y0 + V2;
1377  if ((R >> 8) > 0)
1378  R = 255;
1379  else if (R < 0)
1380  R = 0;
1381 
1382  int G = Y0 + UV;
1383  if ((G >> 8) > 0)
1384  G = 255;
1385  else if (G < 0)
1386  G = 0;
1387 
1388  int B = Y0 + U5;
1389  if ((B >> 8) > 0)
1390  B = 255;
1391  else if (B < 0)
1392  B = 0;
1393 
1394  *rgba++ = (unsigned char)R;
1395  *rgba++ = (unsigned char)G;
1396  *rgba++ = (unsigned char)B;
1397  *rgba++ = vpRGBa::alpha_default;
1398 
1399  //---
1400  R = Y1 + V2;
1401  if ((R >> 8) > 0)
1402  R = 255;
1403  else if (R < 0)
1404  R = 0;
1405 
1406  G = Y1 + UV;
1407  if ((G >> 8) > 0)
1408  G = 255;
1409  else if (G < 0)
1410  G = 0;
1411 
1412  B = Y1 + U5;
1413  if ((B >> 8) > 0)
1414  B = 255;
1415  else if (B < 0)
1416  B = 0;
1417 
1418  *rgba++ = (unsigned char)R;
1419  *rgba++ = (unsigned char)G;
1420  *rgba++ = (unsigned char)B;
1421  *rgba++ = vpRGBa::alpha_default;
1422 
1423  //---
1424  R = Y2 + V2;
1425  if ((R >> 8) > 0)
1426  R = 255;
1427  else if (R < 0)
1428  R = 0;
1429 
1430  G = Y2 + UV;
1431  if ((G >> 8) > 0)
1432  G = 255;
1433  else if (G < 0)
1434  G = 0;
1435 
1436  B = Y2 + U5;
1437  if ((B >> 8) > 0)
1438  B = 255;
1439  else if (B < 0)
1440  B = 0;
1441 
1442  *rgba++ = (unsigned char)R;
1443  *rgba++ = (unsigned char)G;
1444  *rgba++ = (unsigned char)B;
1445  *rgba++ = vpRGBa::alpha_default;
1446 
1447  //---
1448  R = Y3 + V2;
1449  if ((R >> 8) > 0)
1450  R = 255;
1451  else if (R < 0)
1452  R = 0;
1453 
1454  G = Y3 + UV;
1455  if ((G >> 8) > 0)
1456  G = 255;
1457  else if (G < 0)
1458  G = 0;
1459 
1460  B = Y3 + U5;
1461  if ((B >> 8) > 0)
1462  B = 255;
1463  else if (B < 0)
1464  B = 0;
1465 
1466  *rgba++ = (unsigned char)R;
1467  *rgba++ = (unsigned char)G;
1468  *rgba++ = (unsigned char)B;
1469  *rgba++ = vpRGBa::alpha_default;
1470  }
1471 #else
1472  // tres tres lent ....
1473  unsigned int i = 0, j = 0;
1474  unsigned char r, g, b;
1475  while (j < numpixels * 3 / 2) {
1476 
1477  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 3], r, g, b);
1478  rgba[i] = r;
1479  rgba[i + 1] = g;
1480  rgba[i + 2] = b;
1481  rgba[i + 3] = vpRGBa::alpha_default;
1482  i += 4;
1483 
1484  YUVToRGB(yuv[j + 2], yuv[j], yuv[j + 3], r, g, b);
1485  rgba[i] = r;
1486  rgba[i + 1] = g;
1487  rgba[i + 2] = b;
1488  rgba[i + 3] = vpRGBa::alpha_default;
1489  i += 4;
1490 
1491  YUVToRGB(yuv[j + 4], yuv[j], yuv[j + 3], r, g, b);
1492  rgba[i] = r;
1493  rgba[i + 1] = g;
1494  rgba[i + 2] = b;
1495  rgba[i + 3] = vpRGBa::alpha_default;
1496  i += 4;
1497 
1498  YUVToRGB(yuv[j + 5], yuv[j], yuv[j + 3], r, g, b);
1499  rgba[i] = r;
1500  rgba[i + 1] = g;
1501  rgba[i + 2] = b;
1502  rgba[i + 3] = vpRGBa::alpha_default;
1503  i += 4;
1504 
1505  j += 6;
1506  }
1507 #endif
1508 }
1509 
1518 void vpImageConvert::YUV422ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
1519 {
1520 
1521 #if 1
1522  // std::cout << "call optimized convertYUV422ToRGBa()" << std::endl;
1523  for (unsigned int i = size / 2; i; i--) {
1524  int U = (int)((*yuv++ - 128) * 0.354);
1525  int U5 = 5 * U;
1526  int Y0 = *yuv++;
1527  int V = (int)((*yuv++ - 128) * 0.707);
1528  int V2 = 2 * V;
1529  int Y1 = *yuv++;
1530  int UV = -U - V;
1531 
1532  //---
1533  int R = Y0 + V2;
1534  if ((R >> 8) > 0)
1535  R = 255;
1536  else if (R < 0)
1537  R = 0;
1538 
1539  int G = Y0 + UV;
1540  if ((G >> 8) > 0)
1541  G = 255;
1542  else if (G < 0)
1543  G = 0;
1544 
1545  int B = Y0 + U5;
1546  if ((B >> 8) > 0)
1547  B = 255;
1548  else if (B < 0)
1549  B = 0;
1550 
1551  *rgba++ = (unsigned char)R;
1552  *rgba++ = (unsigned char)G;
1553  *rgba++ = (unsigned char)B;
1554  *rgba++ = vpRGBa::alpha_default;
1555 
1556  //---
1557  R = Y1 + V2;
1558  if ((R >> 8) > 0)
1559  R = 255;
1560  else if (R < 0)
1561  R = 0;
1562 
1563  G = Y1 + UV;
1564  if ((G >> 8) > 0)
1565  G = 255;
1566  else if (G < 0)
1567  G = 0;
1568 
1569  B = Y1 + U5;
1570  if ((B >> 8) > 0)
1571  B = 255;
1572  else if (B < 0)
1573  B = 0;
1574 
1575  *rgba++ = (unsigned char)R;
1576  *rgba++ = (unsigned char)G;
1577  *rgba++ = (unsigned char)B;
1578  *rgba++ = vpRGBa::alpha_default;
1579  }
1580 
1581 #else
1582  // tres tres lent ....
1583  unsigned int i = 0, j = 0;
1584  unsigned char r, g, b;
1585 
1586  while (j < size * 2) {
1587 
1588  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 2], r, g, b);
1589  rgba[i] = r;
1590  rgba[i + 1] = g;
1591  rgba[i + 2] = b;
1592  rgba[i + 3] = vpRGBa::alpha_default;
1593  i += 4;
1594 
1595  YUVToRGB(yuv[j + 3], yuv[j], yuv[j + 2], r, g, b);
1596  rgba[i] = r;
1597  rgba[i + 1] = g;
1598  rgba[i + 2] = b;
1599  rgba[i + 3] = vpRGBa::alpha_default;
1600  i += 4;
1601  j += 4;
1602  }
1603 #endif
1604 }
1605 
1612 void vpImageConvert::YUV411ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
1613 {
1614  unsigned int i = 0, j = 0;
1615  while (j < size * 3 / 2) {
1616  grey[i] = yuv[j + 1];
1617  grey[i + 1] = yuv[j + 2];
1618  grey[i + 2] = yuv[j + 4];
1619  grey[i + 3] = yuv[j + 5];
1620 
1621  i += 4;
1622 
1623  j += 6;
1624  }
1625 }
1626 
1635 void vpImageConvert::YUV422ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
1636 {
1637 #if 1
1638  // std::cout << "call optimized convertYUV422ToRGB()" << std::endl;
1639  for (unsigned int i = size / 2; i; i--) {
1640  int U = (int)((*yuv++ - 128) * 0.354);
1641  int U5 = 5 * U;
1642  int Y0 = *yuv++;
1643  int V = (int)((*yuv++ - 128) * 0.707);
1644  int V2 = 2 * V;
1645  int Y1 = *yuv++;
1646  int UV = -U - V;
1647 
1648  //---
1649  int R = Y0 + V2;
1650  if ((R >> 8) > 0)
1651  R = 255;
1652  else if (R < 0)
1653  R = 0;
1654 
1655  int G = Y0 + UV;
1656  if ((G >> 8) > 0)
1657  G = 255;
1658  else if (G < 0)
1659  G = 0;
1660 
1661  int B = Y0 + U5;
1662  if ((B >> 8) > 0)
1663  B = 255;
1664  else if (B < 0)
1665  B = 0;
1666 
1667  *rgb++ = (unsigned char)R;
1668  *rgb++ = (unsigned char)G;
1669  *rgb++ = (unsigned char)B;
1670 
1671  //---
1672  R = Y1 + V2;
1673  if ((R >> 8) > 0)
1674  R = 255;
1675  else if (R < 0)
1676  R = 0;
1677 
1678  G = Y1 + UV;
1679  if ((G >> 8) > 0)
1680  G = 255;
1681  else if (G < 0)
1682  G = 0;
1683 
1684  B = Y1 + U5;
1685  if ((B >> 8) > 0)
1686  B = 255;
1687  else if (B < 0)
1688  B = 0;
1689 
1690  *rgb++ = (unsigned char)R;
1691  *rgb++ = (unsigned char)G;
1692  *rgb++ = (unsigned char)B;
1693  }
1694 
1695 #else
1696  // tres tres lent ....
1697  unsigned int i = 0, j = 0;
1698  unsigned char r, g, b;
1699 
1700  while (j < size * 2) {
1701 
1702  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 2], r, g, b);
1703  rgb[i] = r;
1704  rgb[i + 1] = g;
1705  rgb[i + 2] = b;
1706  i += 3;
1707 
1708  YUVToRGB(yuv[j + 3], yuv[j], yuv[j + 2], r, g, b);
1709  rgb[i] = r;
1710  rgb[i + 1] = g;
1711  rgb[i + 2] = b;
1712  i += 3;
1713  j += 4;
1714  }
1715 #endif
1716 }
1717 
1726 void vpImageConvert::YUV422ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
1727 {
1728  unsigned int i = 0, j = 0;
1729 
1730  while (j < size * 2) {
1731  grey[i++] = yuv[j + 1];
1732  grey[i++] = yuv[j + 3];
1733  j += 4;
1734  }
1735 }
1736 
1743 void vpImageConvert::YUV411ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
1744 {
1745 #if 1
1746  // std::cout << "call optimized ConvertYUV411ToRGB()" << std::endl;
1747  for (unsigned int i = size / 4; i; i--) {
1748  int U = (int)((*yuv++ - 128) * 0.354);
1749  int U5 = 5 * U;
1750  int Y0 = *yuv++;
1751  int Y1 = *yuv++;
1752  int V = (int)((*yuv++ - 128) * 0.707);
1753  int V2 = 2 * V;
1754  int Y2 = *yuv++;
1755  int Y3 = *yuv++;
1756  int UV = -U - V;
1757 
1758  // Original equations
1759  // R = Y + 1.402 V
1760  // G = Y - 0.344 U - 0.714 V
1761  // B = Y + 1.772 U
1762  int R = Y0 + V2;
1763  if ((R >> 8) > 0)
1764  R = 255;
1765  else if (R < 0)
1766  R = 0;
1767 
1768  int G = Y0 + UV;
1769  if ((G >> 8) > 0)
1770  G = 255;
1771  else if (G < 0)
1772  G = 0;
1773 
1774  int B = Y0 + U5;
1775  if ((B >> 8) > 0)
1776  B = 255;
1777  else if (B < 0)
1778  B = 0;
1779 
1780  *rgb++ = (unsigned char)R;
1781  *rgb++ = (unsigned char)G;
1782  *rgb++ = (unsigned char)B;
1783 
1784  //---
1785  R = Y1 + V2;
1786  if ((R >> 8) > 0)
1787  R = 255;
1788  else if (R < 0)
1789  R = 0;
1790 
1791  G = Y1 + UV;
1792  if ((G >> 8) > 0)
1793  G = 255;
1794  else if (G < 0)
1795  G = 0;
1796 
1797  B = Y1 + U5;
1798  if ((B >> 8) > 0)
1799  B = 255;
1800  else if (B < 0)
1801  B = 0;
1802 
1803  *rgb++ = (unsigned char)R;
1804  *rgb++ = (unsigned char)G;
1805  *rgb++ = (unsigned char)B;
1806 
1807  //---
1808  R = Y2 + V2;
1809  if ((R >> 8) > 0)
1810  R = 255;
1811  else if (R < 0)
1812  R = 0;
1813 
1814  G = Y2 + UV;
1815  if ((G >> 8) > 0)
1816  G = 255;
1817  else if (G < 0)
1818  G = 0;
1819 
1820  B = Y2 + U5;
1821  if ((B >> 8) > 0)
1822  B = 255;
1823  else if (B < 0)
1824  B = 0;
1825 
1826  *rgb++ = (unsigned char)R;
1827  *rgb++ = (unsigned char)G;
1828  *rgb++ = (unsigned char)B;
1829 
1830  //---
1831  R = Y3 + V2;
1832  if ((R >> 8) > 0)
1833  R = 255;
1834  else if (R < 0)
1835  R = 0;
1836 
1837  G = Y3 + UV;
1838  if ((G >> 8) > 0)
1839  G = 255;
1840  else if (G < 0)
1841  G = 0;
1842 
1843  B = Y3 + U5;
1844  if ((B >> 8) > 0)
1845  B = 255;
1846  else if (B < 0)
1847  B = 0;
1848 
1849  *rgb++ = (unsigned char)R;
1850  *rgb++ = (unsigned char)G;
1851  *rgb++ = (unsigned char)B;
1852  }
1853 #else
1854  // tres tres lent ....
1855 
1856  unsigned int i = 0, j = 0;
1857  unsigned char r, g, b;
1858 
1859  while (j < size * 3 / 2) {
1860  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 3], r, g, b);
1861  rgb[i] = r;
1862  rgb[i + 1] = g;
1863  rgb[i + 2] = b;
1864  i += 3;
1865 
1866  YUVToRGB(yuv[j + 2], yuv[j], yuv[j + 3], r, g, b);
1867  rgb[i] = r;
1868  rgb[i + 1] = g;
1869  rgb[i + 2] = b;
1870  i += 3;
1871 
1872  YUVToRGB(yuv[j + 4], 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 + 5], 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  // TRACE("r= %d g=%d b=%d", r, g, b);
1884 
1885  j += 6;
1886  }
1887 #endif
1888 }
1889 
1897 void vpImageConvert::YUV420ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
1898 {
1899  // std::cout << "call optimized ConvertYUV420ToRGBa()" << std::endl;
1900  int U, V, R, G, B, V2, U5, UV;
1901  int Y0, Y1, Y2, Y3;
1902  unsigned int size = width * height;
1903  unsigned char *iU = yuv + size;
1904  unsigned char *iV = yuv + 5 * size / 4;
1905  for (unsigned int i = 0; i < height / 2; i++) {
1906  for (unsigned int j = 0; j < width / 2; j++) {
1907  U = (int)((*iU++ - 128) * 0.354);
1908  U5 = 5 * U;
1909  V = (int)((*iV++ - 128) * 0.707);
1910  V2 = 2 * V;
1911  UV = -U - V;
1912  Y0 = *yuv++;
1913  Y1 = *yuv;
1914  yuv = yuv + width - 1;
1915  Y2 = *yuv++;
1916  Y3 = *yuv;
1917  yuv = yuv - width + 1;
1918 
1919  // Original equations
1920  // R = Y + 1.402 V
1921  // G = Y - 0.344 U - 0.714 V
1922  // B = Y + 1.772 U
1923  R = Y0 + V2;
1924  if ((R >> 8) > 0)
1925  R = 255;
1926  else if (R < 0)
1927  R = 0;
1928 
1929  G = Y0 + UV;
1930  if ((G >> 8) > 0)
1931  G = 255;
1932  else if (G < 0)
1933  G = 0;
1934 
1935  B = Y0 + U5;
1936  if ((B >> 8) > 0)
1937  B = 255;
1938  else if (B < 0)
1939  B = 0;
1940 
1941  *rgba++ = (unsigned char)R;
1942  *rgba++ = (unsigned char)G;
1943  *rgba++ = (unsigned char)B;
1944  *rgba++ = vpRGBa::alpha_default;
1945 
1946  //---
1947  R = Y1 + V2;
1948  if ((R >> 8) > 0)
1949  R = 255;
1950  else if (R < 0)
1951  R = 0;
1952 
1953  G = Y1 + UV;
1954  if ((G >> 8) > 0)
1955  G = 255;
1956  else if (G < 0)
1957  G = 0;
1958 
1959  B = Y1 + U5;
1960  if ((B >> 8) > 0)
1961  B = 255;
1962  else if (B < 0)
1963  B = 0;
1964 
1965  *rgba++ = (unsigned char)R;
1966  *rgba++ = (unsigned char)G;
1967  *rgba++ = (unsigned char)B;
1968  *rgba = vpRGBa::alpha_default;
1969  rgba = rgba + 4 * width - 7;
1970 
1971  //---
1972  R = Y2 + V2;
1973  if ((R >> 8) > 0)
1974  R = 255;
1975  else if (R < 0)
1976  R = 0;
1977 
1978  G = Y2 + UV;
1979  if ((G >> 8) > 0)
1980  G = 255;
1981  else if (G < 0)
1982  G = 0;
1983 
1984  B = Y2 + U5;
1985  if ((B >> 8) > 0)
1986  B = 255;
1987  else if (B < 0)
1988  B = 0;
1989 
1990  *rgba++ = (unsigned char)R;
1991  *rgba++ = (unsigned char)G;
1992  *rgba++ = (unsigned char)B;
1993  *rgba++ = vpRGBa::alpha_default;
1994 
1995  //---
1996  R = Y3 + V2;
1997  if ((R >> 8) > 0)
1998  R = 255;
1999  else if (R < 0)
2000  R = 0;
2001 
2002  G = Y3 + UV;
2003  if ((G >> 8) > 0)
2004  G = 255;
2005  else if (G < 0)
2006  G = 0;
2007 
2008  B = Y3 + U5;
2009  if ((B >> 8) > 0)
2010  B = 255;
2011  else if (B < 0)
2012  B = 0;
2013 
2014  *rgba++ = (unsigned char)R;
2015  *rgba++ = (unsigned char)G;
2016  *rgba++ = (unsigned char)B;
2017  *rgba = vpRGBa::alpha_default;
2018  rgba = rgba - 4 * width + 1;
2019  }
2020  yuv += width;
2021  rgba += 4 * width;
2022  }
2023 }
2029 void vpImageConvert::YUV420ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
2030 {
2031  // std::cout << "call optimized ConvertYUV420ToRGB()" << std::endl;
2032  int U, V, R, G, B, V2, U5, UV;
2033  int Y0, Y1, Y2, Y3;
2034  unsigned int size = width * height;
2035  unsigned char *iU = yuv + size;
2036  unsigned char *iV = yuv + 5 * size / 4;
2037  for (unsigned int i = 0; i < height / 2; i++) {
2038  for (unsigned int j = 0; j < width / 2; j++) {
2039  U = (int)((*iU++ - 128) * 0.354);
2040  U5 = 5 * U;
2041  V = (int)((*iV++ - 128) * 0.707);
2042  V2 = 2 * V;
2043  UV = -U - V;
2044  Y0 = *yuv++;
2045  Y1 = *yuv;
2046  yuv = yuv + width - 1;
2047  Y2 = *yuv++;
2048  Y3 = *yuv;
2049  yuv = yuv - width + 1;
2050 
2051  // Original equations
2052  // R = Y + 1.402 V
2053  // G = Y - 0.344 U - 0.714 V
2054  // B = Y + 1.772 U
2055  R = Y0 + V2;
2056  if ((R >> 8) > 0)
2057  R = 255;
2058  else if (R < 0)
2059  R = 0;
2060 
2061  G = Y0 + UV;
2062  if ((G >> 8) > 0)
2063  G = 255;
2064  else if (G < 0)
2065  G = 0;
2066 
2067  B = Y0 + U5;
2068  if ((B >> 8) > 0)
2069  B = 255;
2070  else if (B < 0)
2071  B = 0;
2072 
2073  *rgb++ = (unsigned char)R;
2074  *rgb++ = (unsigned char)G;
2075  *rgb++ = (unsigned char)B;
2076 
2077  //---
2078  R = Y1 + V2;
2079  if ((R >> 8) > 0)
2080  R = 255;
2081  else if (R < 0)
2082  R = 0;
2083 
2084  G = Y1 + UV;
2085  if ((G >> 8) > 0)
2086  G = 255;
2087  else if (G < 0)
2088  G = 0;
2089 
2090  B = Y1 + U5;
2091  if ((B >> 8) > 0)
2092  B = 255;
2093  else if (B < 0)
2094  B = 0;
2095 
2096  *rgb++ = (unsigned char)R;
2097  *rgb++ = (unsigned char)G;
2098  *rgb = (unsigned char)B;
2099  rgb = rgb + 3 * width - 5;
2100 
2101  //---
2102  R = Y2 + V2;
2103  if ((R >> 8) > 0)
2104  R = 255;
2105  else if (R < 0)
2106  R = 0;
2107 
2108  G = Y2 + UV;
2109  if ((G >> 8) > 0)
2110  G = 255;
2111  else if (G < 0)
2112  G = 0;
2113 
2114  B = Y2 + U5;
2115  if ((B >> 8) > 0)
2116  B = 255;
2117  else if (B < 0)
2118  B = 0;
2119 
2120  *rgb++ = (unsigned char)R;
2121  *rgb++ = (unsigned char)G;
2122  *rgb++ = (unsigned char)B;
2123 
2124  //---
2125  R = Y3 + V2;
2126  if ((R >> 8) > 0)
2127  R = 255;
2128  else if (R < 0)
2129  R = 0;
2130 
2131  G = Y3 + UV;
2132  if ((G >> 8) > 0)
2133  G = 255;
2134  else if (G < 0)
2135  G = 0;
2136 
2137  B = Y3 + U5;
2138  if ((B >> 8) > 0)
2139  B = 255;
2140  else if (B < 0)
2141  B = 0;
2142 
2143  *rgb++ = (unsigned char)R;
2144  *rgb++ = (unsigned char)G;
2145  *rgb = (unsigned char)B;
2146  rgb = rgb - 3 * width + 1;
2147  }
2148  yuv += width;
2149  rgb += 3 * width;
2150  }
2151 }
2152 
2158 void vpImageConvert::YUV420ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
2159 {
2160  for (unsigned int i = 0; i < size; i++) {
2161  *grey++ = *yuv++;
2162  }
2163 }
2171 void vpImageConvert::YUV444ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
2172 {
2173  for (unsigned int i = 0; i < size; i++) {
2174  int U = (int)((*yuv++ - 128) * 0.354);
2175  int U5 = 5 * U;
2176  int Y = *yuv++;
2177  int V = (int)((*yuv++ - 128) * 0.707);
2178  int V2 = 2 * V;
2179  int UV = -U - V;
2180 
2181  // Original equations
2182  // R = Y + 1.402 V
2183  // G = Y - 0.344 U - 0.714 V
2184  // B = Y + 1.772 U
2185  int R = Y + V2;
2186  if ((R >> 8) > 0)
2187  R = 255;
2188  else if (R < 0)
2189  R = 0;
2190 
2191  int G = Y + UV;
2192  if ((G >> 8) > 0)
2193  G = 255;
2194  else if (G < 0)
2195  G = 0;
2196 
2197  int B = Y + U5;
2198  if ((B >> 8) > 0)
2199  B = 255;
2200  else if (B < 0)
2201  B = 0;
2202 
2203  *rgba++ = (unsigned char)R;
2204  *rgba++ = (unsigned char)G;
2205  *rgba++ = (unsigned char)B;
2206  *rgba++ = vpRGBa::alpha_default;
2207  }
2208 }
2214 void vpImageConvert::YUV444ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
2215 {
2216  for (unsigned int i = 0; i < size; i++) {
2217  int U = (int)((*yuv++ - 128) * 0.354);
2218  int U5 = 5 * U;
2219  int Y = *yuv++;
2220  int V = (int)((*yuv++ - 128) * 0.707);
2221  int V2 = 2 * V;
2222  int UV = -U - V;
2223 
2224  // Original equations
2225  // R = Y + 1.402 V
2226  // G = Y - 0.344 U - 0.714 V
2227  // B = Y + 1.772 U
2228  int R = Y + V2;
2229  if ((R >> 8) > 0)
2230  R = 255;
2231  else if (R < 0)
2232  R = 0;
2233 
2234  int G = Y + UV;
2235  if ((G >> 8) > 0)
2236  G = 255;
2237  else if (G < 0)
2238  G = 0;
2239 
2240  int B = Y + U5;
2241  if ((B >> 8) > 0)
2242  B = 255;
2243  else if (B < 0)
2244  B = 0;
2245 
2246  *rgb++ = (unsigned char)R;
2247  *rgb++ = (unsigned char)G;
2248  *rgb++ = (unsigned char)B;
2249  }
2250 }
2251 
2257 void vpImageConvert::YUV444ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
2258 {
2259  yuv++;
2260  for (unsigned int i = 0; i < size; i++) {
2261  *grey++ = *yuv;
2262  yuv = yuv + 3;
2263  }
2264 }
2265 
2273 void vpImageConvert::YV12ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
2274 {
2275  // std::cout << "call optimized ConvertYV12ToRGBa()" << std::endl;
2276  int U, V, R, G, B, V2, U5, UV;
2277  int Y0, Y1, Y2, Y3;
2278  unsigned int size = width * height;
2279  unsigned char *iV = yuv + size;
2280  unsigned char *iU = yuv + 5 * size / 4;
2281  for (unsigned int i = 0; i < height / 2; i++) {
2282  for (unsigned int j = 0; j < width / 2; j++) {
2283  U = (int)((*iU++ - 128) * 0.354);
2284  U5 = 5 * U;
2285  V = (int)((*iV++ - 128) * 0.707);
2286  V2 = 2 * V;
2287  UV = -U - V;
2288  Y0 = *yuv++;
2289  Y1 = *yuv;
2290  yuv = yuv + width - 1;
2291  Y2 = *yuv++;
2292  Y3 = *yuv;
2293  yuv = yuv - width + 1;
2294 
2295  // Original equations
2296  // R = Y + 1.402 V
2297  // G = Y - 0.344 U - 0.714 V
2298  // B = Y + 1.772 U
2299  R = Y0 + V2;
2300  if ((R >> 8) > 0)
2301  R = 255;
2302  else if (R < 0)
2303  R = 0;
2304 
2305  G = Y0 + UV;
2306  if ((G >> 8) > 0)
2307  G = 255;
2308  else if (G < 0)
2309  G = 0;
2310 
2311  B = Y0 + U5;
2312  if ((B >> 8) > 0)
2313  B = 255;
2314  else if (B < 0)
2315  B = 0;
2316 
2317  *rgba++ = (unsigned char)R;
2318  *rgba++ = (unsigned char)G;
2319  *rgba++ = (unsigned char)B;
2320  *rgba++ = vpRGBa::alpha_default;
2321 
2322  //---
2323  R = Y1 + V2;
2324  if ((R >> 8) > 0)
2325  R = 255;
2326  else if (R < 0)
2327  R = 0;
2328 
2329  G = Y1 + UV;
2330  if ((G >> 8) > 0)
2331  G = 255;
2332  else if (G < 0)
2333  G = 0;
2334 
2335  B = Y1 + U5;
2336  if ((B >> 8) > 0)
2337  B = 255;
2338  else if (B < 0)
2339  B = 0;
2340 
2341  *rgba++ = (unsigned char)R;
2342  *rgba++ = (unsigned char)G;
2343  *rgba++ = (unsigned char)B;
2344  *rgba = 0;
2345  rgba = rgba + 4 * width - 7;
2346 
2347  //---
2348  R = Y2 + V2;
2349  if ((R >> 8) > 0)
2350  R = 255;
2351  else if (R < 0)
2352  R = 0;
2353 
2354  G = Y2 + UV;
2355  if ((G >> 8) > 0)
2356  G = 255;
2357  else if (G < 0)
2358  G = 0;
2359 
2360  B = Y2 + U5;
2361  if ((B >> 8) > 0)
2362  B = 255;
2363  else if (B < 0)
2364  B = 0;
2365 
2366  *rgba++ = (unsigned char)R;
2367  *rgba++ = (unsigned char)G;
2368  *rgba++ = (unsigned char)B;
2369  *rgba++ = vpRGBa::alpha_default;
2370 
2371  //---
2372  R = Y3 + V2;
2373  if ((R >> 8) > 0)
2374  R = 255;
2375  else if (R < 0)
2376  R = 0;
2377 
2378  G = Y3 + UV;
2379  if ((G >> 8) > 0)
2380  G = 255;
2381  else if (G < 0)
2382  G = 0;
2383 
2384  B = Y3 + U5;
2385  if ((B >> 8) > 0)
2386  B = 255;
2387  else if (B < 0)
2388  B = 0;
2389 
2390  *rgba++ = (unsigned char)R;
2391  *rgba++ = (unsigned char)G;
2392  *rgba++ = (unsigned char)B;
2393  *rgba = vpRGBa::alpha_default;
2394  rgba = rgba - 4 * width + 1;
2395  }
2396  yuv += width;
2397  rgba += 4 * width;
2398  }
2399 }
2405 void vpImageConvert::YV12ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int height, unsigned int width)
2406 {
2407  // std::cout << "call optimized ConvertYV12ToRGB()" << std::endl;
2408  int U, V, R, G, B, V2, U5, UV;
2409  int Y0, Y1, Y2, Y3;
2410  unsigned int size = width * height;
2411  unsigned char *iV = yuv + size;
2412  unsigned char *iU = yuv + 5 * size / 4;
2413  for (unsigned int i = 0; i < height / 2; i++) {
2414  for (unsigned int j = 0; j < width / 2; j++) {
2415  U = (int)((*iU++ - 128) * 0.354);
2416  U5 = 5 * U;
2417  V = (int)((*iV++ - 128) * 0.707);
2418  V2 = 2 * V;
2419  UV = -U - V;
2420  Y0 = *yuv++;
2421  Y1 = *yuv;
2422  yuv = yuv + width - 1;
2423  Y2 = *yuv++;
2424  Y3 = *yuv;
2425  yuv = yuv - width + 1;
2426 
2427  // Original equations
2428  // R = Y + 1.402 V
2429  // G = Y - 0.344 U - 0.714 V
2430  // B = Y + 1.772 U
2431  R = Y0 + V2;
2432  if ((R >> 8) > 0)
2433  R = 255;
2434  else if (R < 0)
2435  R = 0;
2436 
2437  G = Y0 + UV;
2438  if ((G >> 8) > 0)
2439  G = 255;
2440  else if (G < 0)
2441  G = 0;
2442 
2443  B = Y0 + U5;
2444  if ((B >> 8) > 0)
2445  B = 255;
2446  else if (B < 0)
2447  B = 0;
2448 
2449  *rgb++ = (unsigned char)R;
2450  *rgb++ = (unsigned char)G;
2451  *rgb++ = (unsigned char)B;
2452 
2453  //---
2454  R = Y1 + V2;
2455  if ((R >> 8) > 0)
2456  R = 255;
2457  else if (R < 0)
2458  R = 0;
2459 
2460  G = Y1 + UV;
2461  if ((G >> 8) > 0)
2462  G = 255;
2463  else if (G < 0)
2464  G = 0;
2465 
2466  B = Y1 + U5;
2467  if ((B >> 8) > 0)
2468  B = 255;
2469  else if (B < 0)
2470  B = 0;
2471 
2472  *rgb++ = (unsigned char)R;
2473  *rgb++ = (unsigned char)G;
2474  *rgb = (unsigned char)B;
2475  rgb = rgb + 3 * width - 5;
2476 
2477  //---
2478  R = Y2 + V2;
2479  if ((R >> 8) > 0)
2480  R = 255;
2481  else if (R < 0)
2482  R = 0;
2483 
2484  G = Y2 + UV;
2485  if ((G >> 8) > 0)
2486  G = 255;
2487  else if (G < 0)
2488  G = 0;
2489 
2490  B = Y2 + U5;
2491  if ((B >> 8) > 0)
2492  B = 255;
2493  else if (B < 0)
2494  B = 0;
2495 
2496  *rgb++ = (unsigned char)R;
2497  *rgb++ = (unsigned char)G;
2498  *rgb++ = (unsigned char)B;
2499 
2500  //---
2501  R = Y3 + V2;
2502  if ((R >> 8) > 0)
2503  R = 255;
2504  else if (R < 0)
2505  R = 0;
2506 
2507  G = Y3 + UV;
2508  if ((G >> 8) > 0)
2509  G = 255;
2510  else if (G < 0)
2511  G = 0;
2512 
2513  B = Y3 + U5;
2514  if ((B >> 8) > 0)
2515  B = 255;
2516  else if (B < 0)
2517  B = 0;
2518 
2519  *rgb++ = (unsigned char)R;
2520  *rgb++ = (unsigned char)G;
2521  *rgb = (unsigned char)B;
2522  rgb = rgb - 3 * width + 1;
2523  }
2524  yuv += width;
2525  rgb += 3 * width;
2526  }
2527 }
2528 
2536 void vpImageConvert::YVU9ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
2537 {
2538  // std::cout << "call optimized ConvertYVU9ToRGBa()" << std::endl;
2539  int U, V, R, G, B, V2, U5, UV;
2540  int Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9, Y10, Y11, Y12, Y13, Y14, Y15;
2541  unsigned int size = width * height;
2542  unsigned char *iV = yuv + size;
2543  unsigned char *iU = yuv + 17 * size / 16;
2544  for (unsigned int i = 0; i < height / 4; i++) {
2545  for (unsigned int j = 0; j < width / 4; j++) {
2546  U = (int)((*iU++ - 128) * 0.354);
2547  U5 = 5 * U;
2548  V = (int)((*iV++ - 128) * 0.707);
2549  V2 = 2 * V;
2550  UV = -U - V;
2551  Y0 = *yuv++;
2552  Y1 = *yuv++;
2553  Y2 = *yuv++;
2554  Y3 = *yuv;
2555  yuv = yuv + width - 3;
2556  Y4 = *yuv++;
2557  Y5 = *yuv++;
2558  Y6 = *yuv++;
2559  Y7 = *yuv;
2560  yuv = yuv + width - 3;
2561  Y8 = *yuv++;
2562  Y9 = *yuv++;
2563  Y10 = *yuv++;
2564  Y11 = *yuv;
2565  yuv = yuv + width - 3;
2566  Y12 = *yuv++;
2567  Y13 = *yuv++;
2568  Y14 = *yuv++;
2569  Y15 = *yuv;
2570  yuv = yuv - 3 * width + 1;
2571 
2572  // Original equations
2573  // R = Y + 1.402 V
2574  // G = Y - 0.344 U - 0.714 V
2575  // B = Y + 1.772 U
2576  R = Y0 + V2;
2577  if ((R >> 8) > 0)
2578  R = 255;
2579  else if (R < 0)
2580  R = 0;
2581 
2582  G = Y0 + UV;
2583  if ((G >> 8) > 0)
2584  G = 255;
2585  else if (G < 0)
2586  G = 0;
2587 
2588  B = Y0 + U5;
2589  if ((B >> 8) > 0)
2590  B = 255;
2591  else if (B < 0)
2592  B = 0;
2593 
2594  *rgba++ = (unsigned char)R;
2595  *rgba++ = (unsigned char)G;
2596  *rgba++ = (unsigned char)B;
2597  *rgba++ = vpRGBa::alpha_default;
2598 
2599  //---
2600  R = Y1 + V2;
2601  if ((R >> 8) > 0)
2602  R = 255;
2603  else if (R < 0)
2604  R = 0;
2605 
2606  G = Y1 + UV;
2607  if ((G >> 8) > 0)
2608  G = 255;
2609  else if (G < 0)
2610  G = 0;
2611 
2612  B = Y1 + U5;
2613  if ((B >> 8) > 0)
2614  B = 255;
2615  else if (B < 0)
2616  B = 0;
2617 
2618  *rgba++ = (unsigned char)R;
2619  *rgba++ = (unsigned char)G;
2620  *rgba++ = (unsigned char)B;
2621  *rgba++ = vpRGBa::alpha_default;
2622 
2623  //---
2624  R = Y2 + V2;
2625  if ((R >> 8) > 0)
2626  R = 255;
2627  else if (R < 0)
2628  R = 0;
2629 
2630  G = Y2 + UV;
2631  if ((G >> 8) > 0)
2632  G = 255;
2633  else if (G < 0)
2634  G = 0;
2635 
2636  B = Y2 + U5;
2637  if ((B >> 8) > 0)
2638  B = 255;
2639  else if (B < 0)
2640  B = 0;
2641 
2642  *rgba++ = (unsigned char)R;
2643  *rgba++ = (unsigned char)G;
2644  *rgba++ = (unsigned char)B;
2645  *rgba++ = vpRGBa::alpha_default;
2646 
2647  //---
2648  R = Y3 + V2;
2649  if ((R >> 8) > 0)
2650  R = 255;
2651  else if (R < 0)
2652  R = 0;
2653 
2654  G = Y3 + UV;
2655  if ((G >> 8) > 0)
2656  G = 255;
2657  else if (G < 0)
2658  G = 0;
2659 
2660  B = Y3 + U5;
2661  if ((B >> 8) > 0)
2662  B = 255;
2663  else if (B < 0)
2664  B = 0;
2665 
2666  *rgba++ = (unsigned char)R;
2667  *rgba++ = (unsigned char)G;
2668  *rgba++ = (unsigned char)B;
2669  *rgba = vpRGBa::alpha_default;
2670  rgba = rgba + 4 * width - 15;
2671 
2672  R = Y4 + V2;
2673  if ((R >> 8) > 0)
2674  R = 255;
2675  else if (R < 0)
2676  R = 0;
2677 
2678  G = Y4 + UV;
2679  if ((G >> 8) > 0)
2680  G = 255;
2681  else if (G < 0)
2682  G = 0;
2683 
2684  B = Y4 + U5;
2685  if ((B >> 8) > 0)
2686  B = 255;
2687  else if (B < 0)
2688  B = 0;
2689 
2690  *rgba++ = (unsigned char)R;
2691  *rgba++ = (unsigned char)G;
2692  *rgba++ = (unsigned char)B;
2693  *rgba++ = vpRGBa::alpha_default;
2694 
2695  //---
2696  R = Y5 + V2;
2697  if ((R >> 8) > 0)
2698  R = 255;
2699  else if (R < 0)
2700  R = 0;
2701 
2702  G = Y5 + UV;
2703  if ((G >> 8) > 0)
2704  G = 255;
2705  else if (G < 0)
2706  G = 0;
2707 
2708  B = Y5 + U5;
2709  if ((B >> 8) > 0)
2710  B = 255;
2711  else if (B < 0)
2712  B = 0;
2713 
2714  *rgba++ = (unsigned char)R;
2715  *rgba++ = (unsigned char)G;
2716  *rgba++ = (unsigned char)B;
2717  *rgba++ = vpRGBa::alpha_default;
2718 
2719  //---
2720  R = Y6 + V2;
2721  if ((R >> 8) > 0)
2722  R = 255;
2723  else if (R < 0)
2724  R = 0;
2725 
2726  G = Y6 + UV;
2727  if ((G >> 8) > 0)
2728  G = 255;
2729  else if (G < 0)
2730  G = 0;
2731 
2732  B = Y6 + U5;
2733  if ((B >> 8) > 0)
2734  B = 255;
2735  else if (B < 0)
2736  B = 0;
2737 
2738  *rgba++ = (unsigned char)R;
2739  *rgba++ = (unsigned char)G;
2740  *rgba++ = (unsigned char)B;
2741  *rgba++ = vpRGBa::alpha_default;
2742 
2743  //---
2744  R = Y7 + V2;
2745  if ((R >> 8) > 0)
2746  R = 255;
2747  else if (R < 0)
2748  R = 0;
2749 
2750  G = Y7 + UV;
2751  if ((G >> 8) > 0)
2752  G = 255;
2753  else if (G < 0)
2754  G = 0;
2755 
2756  B = Y7 + U5;
2757  if ((B >> 8) > 0)
2758  B = 255;
2759  else if (B < 0)
2760  B = 0;
2761 
2762  *rgba++ = (unsigned char)R;
2763  *rgba++ = (unsigned char)G;
2764  *rgba++ = (unsigned char)B;
2765  *rgba = vpRGBa::alpha_default;
2766  rgba = rgba + 4 * width - 15;
2767 
2768  R = Y8 + V2;
2769  if ((R >> 8) > 0)
2770  R = 255;
2771  else if (R < 0)
2772  R = 0;
2773 
2774  G = Y8 + UV;
2775  if ((G >> 8) > 0)
2776  G = 255;
2777  else if (G < 0)
2778  G = 0;
2779 
2780  B = Y8 + U5;
2781  if ((B >> 8) > 0)
2782  B = 255;
2783  else if (B < 0)
2784  B = 0;
2785 
2786  *rgba++ = (unsigned char)R;
2787  *rgba++ = (unsigned char)G;
2788  *rgba++ = (unsigned char)B;
2789  *rgba++ = vpRGBa::alpha_default;
2790 
2791  //---
2792  R = Y9 + V2;
2793  if ((R >> 8) > 0)
2794  R = 255;
2795  else if (R < 0)
2796  R = 0;
2797 
2798  G = Y9 + UV;
2799  if ((G >> 8) > 0)
2800  G = 255;
2801  else if (G < 0)
2802  G = 0;
2803 
2804  B = Y9 + U5;
2805  if ((B >> 8) > 0)
2806  B = 255;
2807  else if (B < 0)
2808  B = 0;
2809 
2810  *rgba++ = (unsigned char)R;
2811  *rgba++ = (unsigned char)G;
2812  *rgba++ = (unsigned char)B;
2813  *rgba++ = vpRGBa::alpha_default;
2814 
2815  //---
2816  R = Y10 + V2;
2817  if ((R >> 8) > 0)
2818  R = 255;
2819  else if (R < 0)
2820  R = 0;
2821 
2822  G = Y10 + UV;
2823  if ((G >> 8) > 0)
2824  G = 255;
2825  else if (G < 0)
2826  G = 0;
2827 
2828  B = Y10 + U5;
2829  if ((B >> 8) > 0)
2830  B = 255;
2831  else if (B < 0)
2832  B = 0;
2833 
2834  *rgba++ = (unsigned char)R;
2835  *rgba++ = (unsigned char)G;
2836  *rgba++ = (unsigned char)B;
2837  *rgba++ = vpRGBa::alpha_default;
2838 
2839  //---
2840  R = Y11 + V2;
2841  if ((R >> 8) > 0)
2842  R = 255;
2843  else if (R < 0)
2844  R = 0;
2845 
2846  G = Y11 + UV;
2847  if ((G >> 8) > 0)
2848  G = 255;
2849  else if (G < 0)
2850  G = 0;
2851 
2852  B = Y11 + U5;
2853  if ((B >> 8) > 0)
2854  B = 255;
2855  else if (B < 0)
2856  B = 0;
2857 
2858  *rgba++ = (unsigned char)R;
2859  *rgba++ = (unsigned char)G;
2860  *rgba++ = (unsigned char)B;
2861  *rgba = vpRGBa::alpha_default;
2862  rgba = rgba + 4 * width - 15;
2863 
2864  R = Y12 + V2;
2865  if ((R >> 8) > 0)
2866  R = 255;
2867  else if (R < 0)
2868  R = 0;
2869 
2870  G = Y12 + UV;
2871  if ((G >> 8) > 0)
2872  G = 255;
2873  else if (G < 0)
2874  G = 0;
2875 
2876  B = Y12 + U5;
2877  if ((B >> 8) > 0)
2878  B = 255;
2879  else if (B < 0)
2880  B = 0;
2881 
2882  *rgba++ = (unsigned char)R;
2883  *rgba++ = (unsigned char)G;
2884  *rgba++ = (unsigned char)B;
2885  *rgba++ = vpRGBa::alpha_default;
2886 
2887  //---
2888  R = Y13 + V2;
2889  if ((R >> 8) > 0)
2890  R = 255;
2891  else if (R < 0)
2892  R = 0;
2893 
2894  G = Y13 + UV;
2895  if ((G >> 8) > 0)
2896  G = 255;
2897  else if (G < 0)
2898  G = 0;
2899 
2900  B = Y13 + U5;
2901  if ((B >> 8) > 0)
2902  B = 255;
2903  else if (B < 0)
2904  B = 0;
2905 
2906  *rgba++ = (unsigned char)R;
2907  *rgba++ = (unsigned char)G;
2908  *rgba++ = (unsigned char)B;
2909  *rgba++ = vpRGBa::alpha_default;
2910 
2911  //---
2912  R = Y14 + V2;
2913  if ((R >> 8) > 0)
2914  R = 255;
2915  else if (R < 0)
2916  R = 0;
2917 
2918  G = Y14 + UV;
2919  if ((G >> 8) > 0)
2920  G = 255;
2921  else if (G < 0)
2922  G = 0;
2923 
2924  B = Y14 + U5;
2925  if ((B >> 8) > 0)
2926  B = 255;
2927  else if (B < 0)
2928  B = 0;
2929 
2930  *rgba++ = (unsigned char)R;
2931  *rgba++ = (unsigned char)G;
2932  *rgba++ = (unsigned char)B;
2933  *rgba++ = vpRGBa::alpha_default;
2934 
2935  //---
2936  R = Y15 + V2;
2937  if ((R >> 8) > 0)
2938  R = 255;
2939  else if (R < 0)
2940  R = 0;
2941 
2942  G = Y15 + UV;
2943  if ((G >> 8) > 0)
2944  G = 255;
2945  else if (G < 0)
2946  G = 0;
2947 
2948  B = Y15 + U5;
2949  if ((B >> 8) > 0)
2950  B = 255;
2951  else if (B < 0)
2952  B = 0;
2953 
2954  *rgba++ = (unsigned char)R;
2955  *rgba++ = (unsigned char)G;
2956  *rgba++ = (unsigned char)B;
2957  *rgba = vpRGBa::alpha_default;
2958  rgba = rgba - 12 * width + 1;
2959  }
2960  yuv += 3 * width;
2961  rgba += 12 * width;
2962  }
2963 }
2969 void vpImageConvert::YVU9ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int height, unsigned int width)
2970 {
2971  // std::cout << "call optimized ConvertYVU9ToRGB()" << std::endl;
2972  int U, V, R, G, B, V2, U5, UV;
2973  int Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9, Y10, Y11, Y12, Y13, Y14, Y15;
2974  unsigned int size = width * height;
2975  unsigned char *iV = yuv + size;
2976  unsigned char *iU = yuv + 17 * size / 16;
2977  for (unsigned int i = 0; i < height / 4; i++) {
2978  for (unsigned int j = 0; j < width / 4; j++) {
2979  U = (int)((*iU++ - 128) * 0.354);
2980  U5 = 5 * U;
2981  V = (int)((*iV++ - 128) * 0.707);
2982  V2 = 2 * V;
2983  UV = -U - V;
2984  Y0 = *yuv++;
2985  Y1 = *yuv++;
2986  Y2 = *yuv++;
2987  Y3 = *yuv;
2988  yuv = yuv + width - 3;
2989  Y4 = *yuv++;
2990  Y5 = *yuv++;
2991  Y6 = *yuv++;
2992  Y7 = *yuv;
2993  yuv = yuv + width - 3;
2994  Y8 = *yuv++;
2995  Y9 = *yuv++;
2996  Y10 = *yuv++;
2997  Y11 = *yuv;
2998  yuv = yuv + width - 3;
2999  Y12 = *yuv++;
3000  Y13 = *yuv++;
3001  Y14 = *yuv++;
3002  Y15 = *yuv;
3003  yuv = yuv - 3 * width + 1;
3004 
3005  // Original equations
3006  // R = Y + 1.402 V
3007  // G = Y - 0.344 U - 0.714 V
3008  // B = Y + 1.772 U
3009  R = Y0 + V2;
3010  if ((R >> 8) > 0)
3011  R = 255;
3012  else if (R < 0)
3013  R = 0;
3014 
3015  G = Y0 + UV;
3016  if ((G >> 8) > 0)
3017  G = 255;
3018  else if (G < 0)
3019  G = 0;
3020 
3021  B = Y0 + U5;
3022  if ((B >> 8) > 0)
3023  B = 255;
3024  else if (B < 0)
3025  B = 0;
3026 
3027  *rgb++ = (unsigned char)R;
3028  *rgb++ = (unsigned char)G;
3029  *rgb++ = (unsigned char)B;
3030 
3031  //---
3032  R = Y1 + V2;
3033  if ((R >> 8) > 0)
3034  R = 255;
3035  else if (R < 0)
3036  R = 0;
3037 
3038  G = Y1 + UV;
3039  if ((G >> 8) > 0)
3040  G = 255;
3041  else if (G < 0)
3042  G = 0;
3043 
3044  B = Y1 + U5;
3045  if ((B >> 8) > 0)
3046  B = 255;
3047  else if (B < 0)
3048  B = 0;
3049 
3050  *rgb++ = (unsigned char)R;
3051  *rgb++ = (unsigned char)G;
3052  *rgb++ = (unsigned char)B;
3053 
3054  //---
3055  R = Y2 + V2;
3056  if ((R >> 8) > 0)
3057  R = 255;
3058  else if (R < 0)
3059  R = 0;
3060 
3061  G = Y2 + UV;
3062  if ((G >> 8) > 0)
3063  G = 255;
3064  else if (G < 0)
3065  G = 0;
3066 
3067  B = Y2 + U5;
3068  if ((B >> 8) > 0)
3069  B = 255;
3070  else if (B < 0)
3071  B = 0;
3072 
3073  *rgb++ = (unsigned char)R;
3074  *rgb++ = (unsigned char)G;
3075  *rgb++ = (unsigned char)B;
3076 
3077  //---
3078  R = Y3 + V2;
3079  if ((R >> 8) > 0)
3080  R = 255;
3081  else if (R < 0)
3082  R = 0;
3083 
3084  G = Y3 + UV;
3085  if ((G >> 8) > 0)
3086  G = 255;
3087  else if (G < 0)
3088  G = 0;
3089 
3090  B = Y3 + U5;
3091  if ((B >> 8) > 0)
3092  B = 255;
3093  else if (B < 0)
3094  B = 0;
3095 
3096  *rgb++ = (unsigned char)R;
3097  *rgb++ = (unsigned char)G;
3098  *rgb = (unsigned char)B;
3099  rgb = rgb + 3 * width - 11;
3100 
3101  R = Y4 + V2;
3102  if ((R >> 8) > 0)
3103  R = 255;
3104  else if (R < 0)
3105  R = 0;
3106 
3107  G = Y4 + UV;
3108  if ((G >> 8) > 0)
3109  G = 255;
3110  else if (G < 0)
3111  G = 0;
3112 
3113  B = Y4 + U5;
3114  if ((B >> 8) > 0)
3115  B = 255;
3116  else if (B < 0)
3117  B = 0;
3118 
3119  *rgb++ = (unsigned char)R;
3120  *rgb++ = (unsigned char)G;
3121  *rgb++ = (unsigned char)B;
3122 
3123  //---
3124  R = Y5 + V2;
3125  if ((R >> 8) > 0)
3126  R = 255;
3127  else if (R < 0)
3128  R = 0;
3129 
3130  G = Y5 + UV;
3131  if ((G >> 8) > 0)
3132  G = 255;
3133  else if (G < 0)
3134  G = 0;
3135 
3136  B = Y5 + U5;
3137  if ((B >> 8) > 0)
3138  B = 255;
3139  else if (B < 0)
3140  B = 0;
3141 
3142  *rgb++ = (unsigned char)R;
3143  *rgb++ = (unsigned char)G;
3144  *rgb++ = (unsigned char)B;
3145 
3146  //---
3147  R = Y6 + V2;
3148  if ((R >> 8) > 0)
3149  R = 255;
3150  else if (R < 0)
3151  R = 0;
3152 
3153  G = Y6 + UV;
3154  if ((G >> 8) > 0)
3155  G = 255;
3156  else if (G < 0)
3157  G = 0;
3158 
3159  B = Y6 + U5;
3160  if ((B >> 8) > 0)
3161  B = 255;
3162  else if (B < 0)
3163  B = 0;
3164 
3165  *rgb++ = (unsigned char)R;
3166  *rgb++ = (unsigned char)G;
3167  *rgb++ = (unsigned char)B;
3168 
3169  //---
3170  R = Y7 + V2;
3171  if ((R >> 8) > 0)
3172  R = 255;
3173  else if (R < 0)
3174  R = 0;
3175 
3176  G = Y7 + UV;
3177  if ((G >> 8) > 0)
3178  G = 255;
3179  else if (G < 0)
3180  G = 0;
3181 
3182  B = Y7 + U5;
3183  if ((B >> 8) > 0)
3184  B = 255;
3185  else if (B < 0)
3186  B = 0;
3187 
3188  *rgb++ = (unsigned char)R;
3189  *rgb++ = (unsigned char)G;
3190  *rgb = (unsigned char)B;
3191  rgb = rgb + 3 * width - 11;
3192 
3193  R = Y8 + V2;
3194  if ((R >> 8) > 0)
3195  R = 255;
3196  else if (R < 0)
3197  R = 0;
3198 
3199  G = Y8 + UV;
3200  if ((G >> 8) > 0)
3201  G = 255;
3202  else if (G < 0)
3203  G = 0;
3204 
3205  B = Y8 + U5;
3206  if ((B >> 8) > 0)
3207  B = 255;
3208  else if (B < 0)
3209  B = 0;
3210 
3211  *rgb++ = (unsigned char)R;
3212  *rgb++ = (unsigned char)G;
3213  *rgb++ = (unsigned char)B;
3214 
3215  //---
3216  R = Y9 + V2;
3217  if ((R >> 8) > 0)
3218  R = 255;
3219  else if (R < 0)
3220  R = 0;
3221 
3222  G = Y9 + UV;
3223  if ((G >> 8) > 0)
3224  G = 255;
3225  else if (G < 0)
3226  G = 0;
3227 
3228  B = Y9 + U5;
3229  if ((B >> 8) > 0)
3230  B = 255;
3231  else if (B < 0)
3232  B = 0;
3233 
3234  *rgb++ = (unsigned char)R;
3235  *rgb++ = (unsigned char)G;
3236  *rgb++ = (unsigned char)B;
3237 
3238  //---
3239  R = Y10 + V2;
3240  if ((R >> 8) > 0)
3241  R = 255;
3242  else if (R < 0)
3243  R = 0;
3244 
3245  G = Y10 + UV;
3246  if ((G >> 8) > 0)
3247  G = 255;
3248  else if (G < 0)
3249  G = 0;
3250 
3251  B = Y10 + U5;
3252  if ((B >> 8) > 0)
3253  B = 255;
3254  else if (B < 0)
3255  B = 0;
3256 
3257  *rgb++ = (unsigned char)R;
3258  *rgb++ = (unsigned char)G;
3259  *rgb++ = (unsigned char)B;
3260 
3261  //---
3262  R = Y11 + V2;
3263  if ((R >> 8) > 0)
3264  R = 255;
3265  else if (R < 0)
3266  R = 0;
3267 
3268  G = Y11 + UV;
3269  if ((G >> 8) > 0)
3270  G = 255;
3271  else if (G < 0)
3272  G = 0;
3273 
3274  B = Y11 + U5;
3275  if ((B >> 8) > 0)
3276  B = 255;
3277  else if (B < 0)
3278  B = 0;
3279 
3280  *rgb++ = (unsigned char)R;
3281  *rgb++ = (unsigned char)G;
3282  *rgb = (unsigned char)B;
3283  rgb = rgb + 3 * width - 11;
3284 
3285  R = Y12 + V2;
3286  if ((R >> 8) > 0)
3287  R = 255;
3288  else if (R < 0)
3289  R = 0;
3290 
3291  G = Y12 + UV;
3292  if ((G >> 8) > 0)
3293  G = 255;
3294  else if (G < 0)
3295  G = 0;
3296 
3297  B = Y12 + U5;
3298  if ((B >> 8) > 0)
3299  B = 255;
3300  else if (B < 0)
3301  B = 0;
3302 
3303  *rgb++ = (unsigned char)R;
3304  *rgb++ = (unsigned char)G;
3305  *rgb++ = (unsigned char)B;
3306 
3307  //---
3308  R = Y13 + V2;
3309  if ((R >> 8) > 0)
3310  R = 255;
3311  else if (R < 0)
3312  R = 0;
3313 
3314  G = Y13 + UV;
3315  if ((G >> 8) > 0)
3316  G = 255;
3317  else if (G < 0)
3318  G = 0;
3319 
3320  B = Y13 + U5;
3321  if ((B >> 8) > 0)
3322  B = 255;
3323  else if (B < 0)
3324  B = 0;
3325 
3326  *rgb++ = (unsigned char)R;
3327  *rgb++ = (unsigned char)G;
3328  *rgb++ = (unsigned char)B;
3329 
3330  //---
3331  R = Y14 + V2;
3332  if ((R >> 8) > 0)
3333  R = 255;
3334  else if (R < 0)
3335  R = 0;
3336 
3337  G = Y14 + UV;
3338  if ((G >> 8) > 0)
3339  G = 255;
3340  else if (G < 0)
3341  G = 0;
3342 
3343  B = Y14 + U5;
3344  if ((B >> 8) > 0)
3345  B = 255;
3346  else if (B < 0)
3347  B = 0;
3348 
3349  *rgb++ = (unsigned char)R;
3350  *rgb++ = (unsigned char)G;
3351  *rgb++ = (unsigned char)B;
3352 
3353  //---
3354  R = Y15 + V2;
3355  if ((R >> 8) > 0)
3356  R = 255;
3357  else if (R < 0)
3358  R = 0;
3359 
3360  G = Y15 + UV;
3361  if ((G >> 8) > 0)
3362  G = 255;
3363  else if (G < 0)
3364  G = 0;
3365 
3366  B = Y15 + U5;
3367  if ((B >> 8) > 0)
3368  B = 255;
3369  else if (B < 0)
3370  B = 0;
3371 
3372  *rgb++ = (unsigned char)R;
3373  *rgb++ = (unsigned char)G;
3374  *rgb++ = (unsigned char)B;
3375  rgb = rgb - 9 * width + 1;
3376  }
3377  yuv += 3 * width;
3378  rgb += 9 * width;
3379  }
3380 }
3381 
3389 void vpImageConvert::RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
3390 {
3391  unsigned char *pt_input = rgb;
3392  unsigned char *pt_end = rgb + 3 * size;
3393  unsigned char *pt_output = rgba;
3394 
3395  while (pt_input != pt_end) {
3396  *(pt_output++) = *(pt_input++); // R
3397  *(pt_output++) = *(pt_input++); // G
3398  *(pt_output++) = *(pt_input++); // B
3399  *(pt_output++) = vpRGBa::alpha_default; // A
3400  }
3401 }
3402 
3410 void vpImageConvert::RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
3411 {
3412  unsigned char *pt_input = rgba;
3413  unsigned char *pt_end = rgba + 4 * size;
3414  unsigned char *pt_output = rgb;
3415 
3416  while (pt_input != pt_end) {
3417  *(pt_output++) = *(pt_input++); // R
3418  *(pt_output++) = *(pt_input++); // G
3419  *(pt_output++) = *(pt_input++); // B
3420  pt_input++;
3421  }
3422 }
3429 void vpImageConvert::RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int size)
3430 {
3431  bool checkSSSE3 = vpCPUFeatures::checkSSSE3();
3432 #if !VISP_HAVE_SSSE3
3433  checkSSSE3 = false;
3434 #endif
3435 
3436  if (checkSSSE3) {
3437 #if VISP_HAVE_SSSE3
3438  unsigned int i = 0;
3439 
3440  if (size >= 16) {
3441  // Mask to select R component
3442  const __m128i mask_R1 = _mm_set_epi8(-1, -1, -1, -1, 15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1);
3443  const __m128i mask_R2 = _mm_set_epi8(5, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3444  const __m128i mask_R3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1);
3445  const __m128i mask_R4 = _mm_set_epi8(13, -1, 10, -1, 7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1);
3446 
3447  // Mask to select G component
3448  const __m128i mask_G1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 13, -1, 10, -1, 7, -1, 4, -1, 1, -1);
3449  const __m128i mask_G2 = _mm_set_epi8(6, -1, 3, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3450  const __m128i mask_G3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 12, -1, 9, -1);
3451  const __m128i mask_G4 = _mm_set_epi8(14, -1, 11, -1, 8, -1, 5, -1, 2, -1, -1, -1, -1, -1, -1, -1);
3452 
3453  // Mask to select B component
3454  const __m128i mask_B1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1, 5, -1, 2, -1);
3455  const __m128i mask_B2 = _mm_set_epi8(7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3456  const __m128i mask_B3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 10, -1);
3457  const __m128i mask_B4 = _mm_set_epi8(15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1, -1, -1, -1, -1);
3458 
3459  // Mask to select the gray component
3460  const __m128i mask_low1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1);
3461  const __m128i mask_low2 = _mm_set_epi8(15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1);
3462 
3463  // Coefficients RGB to Gray
3464  const __m128i coeff_R = _mm_set_epi16(13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933);
3465  const __m128i coeff_G = _mm_set_epi16((short int)46871, (short int)46871, (short int)46871, (short int)46871,
3466  (short int)46871, (short int)46871, (short int)46871, (short int)46871);
3467  const __m128i coeff_B = _mm_set_epi16(4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732);
3468 
3469  for (; i <= size - 16; i += 16) {
3470  // Process 16 color pixels
3471  const __m128i data1 = _mm_loadu_si128((const __m128i *)rgb);
3472  const __m128i data2 = _mm_loadu_si128((const __m128i *)(rgb + 16));
3473  const __m128i data3 = _mm_loadu_si128((const __m128i *)(rgb + 32));
3474 
3475  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3476  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3477  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3478 
3479  const __m128i grays_0_7 =
3480  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3481  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3482 
3483  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4));
3484  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4));
3485  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4));
3486 
3487  const __m128i grays_8_15 =
3488  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R),
3489  _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G), _mm_mulhi_epu16(blue_8_15, coeff_B)));
3490 
3491  _mm_storeu_si128((__m128i *)grey,
3492  _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1), _mm_shuffle_epi8(grays_8_15, mask_low2)));
3493 
3494  rgb += 48;
3495  grey += 16;
3496  }
3497  }
3498 
3499  for (; i < size; i++) {
3500  *grey = (unsigned char)(0.2126 * (*rgb) + 0.7152 * (*(rgb + 1)) + 0.0722 * (*(rgb + 2)));
3501 
3502  rgb += 3;
3503  ++grey;
3504  }
3505 #endif
3506  } else {
3507  unsigned char *pt_input = rgb;
3508  unsigned char *pt_end = rgb + size * 3;
3509  unsigned char *pt_output = grey;
3510 
3511  while (pt_input != pt_end) {
3512  *pt_output = (unsigned char)(0.2126 * (*pt_input) + 0.7152 * (*(pt_input + 1)) + 0.0722 * (*(pt_input + 2)));
3513  pt_input += 3;
3514  pt_output++;
3515  }
3516  }
3517 }
3525 void vpImageConvert::RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int size)
3526 {
3527  bool checkSSSE3 = vpCPUFeatures::checkSSSE3();
3528 #if !VISP_HAVE_SSSE3
3529  checkSSSE3 = false;
3530 #endif
3531 
3532  if (checkSSSE3) {
3533 #if VISP_HAVE_SSSE3
3534  unsigned int i = 0;
3535 
3536  if (size >= 16) {
3537  // Mask to select R component
3538  const __m128i mask_R1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 12, -1, 8, -1, 4, -1, 0, -1);
3539  const __m128i mask_R2 = _mm_set_epi8(12, -1, 8, -1, 4, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3540 
3541  // Mask to select G component
3542  const __m128i mask_G1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 9, -1, 5, -1, 1, -1);
3543  const __m128i mask_G2 = _mm_set_epi8(13, -1, 9, -1, 5, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3544 
3545  // Mask to select B component
3546  const __m128i mask_B1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 10, -1, 6, -1, 2, -1);
3547  const __m128i mask_B2 = _mm_set_epi8(14, -1, 10, -1, 6, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3548 
3549  // Mask to select the gray component
3550  const __m128i mask_low1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1);
3551  const __m128i mask_low2 = _mm_set_epi8(15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1);
3552 
3553  // Coefficients RGB to Gray
3554  const __m128i coeff_R = _mm_set_epi16(13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933);
3555  const __m128i coeff_G = _mm_set_epi16((short int)46871, (short int)46871, (short int)46871, (short int)46871,
3556  (short int)46871, (short int)46871, (short int)46871, (short int)46871);
3557  const __m128i coeff_B = _mm_set_epi16(4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732);
3558 
3559  for (; i <= size - 16; i += 16) {
3560  // Process 2*4 color pixels
3561  const __m128i data1 = _mm_loadu_si128((const __m128i *)rgba);
3562  const __m128i data2 = _mm_loadu_si128((const __m128i *)(rgba + 16));
3563 
3564  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3565  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3566  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3567 
3568  const __m128i grays_0_7 =
3569  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3570  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3571 
3572  // Process next 2*4 color pixels
3573  const __m128i data3 = _mm_loadu_si128((const __m128i *)(rgba + 32));
3574  const __m128i data4 = _mm_loadu_si128((const __m128i *)(rgba + 48));
3575 
3576  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data3, mask_R1), _mm_shuffle_epi8(data4, mask_R2));
3577  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data3, mask_G1), _mm_shuffle_epi8(data4, mask_G2));
3578  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data3, mask_B1), _mm_shuffle_epi8(data4, mask_B2));
3579 
3580  const __m128i grays_8_15 =
3581  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R),
3582  _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G), _mm_mulhi_epu16(blue_8_15, coeff_B)));
3583 
3584  _mm_storeu_si128((__m128i *)grey,
3585  _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1), _mm_shuffle_epi8(grays_8_15, mask_low2)));
3586 
3587  rgba += 64;
3588  grey += 16;
3589  }
3590  }
3591 
3592  for (; i < size; i++) {
3593  *grey = (unsigned char)(0.2126 * (*rgba) + 0.7152 * (*(rgba + 1)) + 0.0722 * (*(rgba + 2)));
3594 
3595  rgba += 4;
3596  ++grey;
3597  }
3598 #endif
3599  } else {
3600  unsigned char *pt_input = rgba;
3601  unsigned char *pt_end = rgba + size * 4;
3602  unsigned char *pt_output = grey;
3603 
3604  while (pt_input != pt_end) {
3605  *pt_output = (unsigned char)(0.2126 * (*pt_input) + 0.7152 * (*(pt_input + 1)) + 0.0722 * (*(pt_input + 2)));
3606  pt_input += 4;
3607  pt_output++;
3608  }
3609  }
3610 }
3611 
3617 void vpImageConvert::GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int size)
3618 {
3619  unsigned char *pt_input = grey;
3620  unsigned char *pt_end = grey + size;
3621  unsigned char *pt_output = rgba;
3622 
3623  while (pt_input != pt_end) {
3624  unsigned char p = *pt_input;
3625  *(pt_output) = p; // R
3626  *(pt_output + 1) = p; // G
3627  *(pt_output + 2) = p; // B
3628  *(pt_output + 3) = vpRGBa::alpha_default; // A
3629 
3630  pt_input++;
3631  pt_output += 4;
3632  }
3633 }
3634 
3639 void vpImageConvert::GreyToRGB(unsigned char *grey, unsigned char *rgb, unsigned int size)
3640 {
3641  unsigned char *pt_input = grey;
3642  unsigned char *pt_end = grey + size;
3643  unsigned char *pt_output = rgb;
3644 
3645  while (pt_input != pt_end) {
3646  unsigned char p = *pt_input;
3647  *(pt_output) = p; // R
3648  *(pt_output + 1) = p; // G
3649  *(pt_output + 2) = p; // B
3650 
3651  pt_input++;
3652  pt_output += 3;
3653  }
3654 }
3655 
3663 void vpImageConvert::BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height,
3664  bool flip)
3665 {
3666  // if we have to flip the image, we start from the end last scanline so the
3667  // step is negative
3668  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
3669 
3670  // starting source address = last line if we need to flip the image
3671  unsigned char *src = (flip) ? (bgr + (width * height * 3) + lineStep) : bgr;
3672 
3673  for (unsigned int i = 0; i < height; i++) {
3674  unsigned char *line = src;
3675  for (unsigned int j = 0; j < width; j++) {
3676  *rgba++ = *(line + 2);
3677  *rgba++ = *(line + 1);
3678  *rgba++ = *(line + 0);
3679  *rgba++ = vpRGBa::alpha_default;
3680 
3681  line += 3;
3682  }
3683  // go to the next line
3684  src += lineStep;
3685  }
3686 }
3687 
3693 void vpImageConvert::BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height,
3694  bool flip)
3695 {
3696  bool checkSSSE3 = vpCPUFeatures::checkSSSE3();
3697 #if !VISP_HAVE_SSSE3
3698  checkSSSE3 = false;
3699 #endif
3700 
3701  if (checkSSSE3) {
3702 #if VISP_HAVE_SSSE3
3703  // Mask to select B component
3704  const __m128i mask_B1 = _mm_set_epi8(-1, -1, -1, -1, 15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1);
3705  const __m128i mask_B2 = _mm_set_epi8(5, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3706  const __m128i mask_B3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1);
3707  const __m128i mask_B4 = _mm_set_epi8(13, -1, 10, -1, 7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1);
3708 
3709  // Mask to select G component
3710  const __m128i mask_G1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 13, -1, 10, -1, 7, -1, 4, -1, 1, -1);
3711  const __m128i mask_G2 = _mm_set_epi8(6, -1, 3, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3712  const __m128i mask_G3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 12, -1, 9, -1);
3713  const __m128i mask_G4 = _mm_set_epi8(14, -1, 11, -1, 8, -1, 5, -1, 2, -1, -1, -1, -1, -1, -1, -1);
3714 
3715  // Mask to select R component
3716  const __m128i mask_R1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1, 5, -1, 2, -1);
3717  const __m128i mask_R2 = _mm_set_epi8(7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3718  const __m128i mask_R3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 10, -1);
3719  const __m128i mask_R4 = _mm_set_epi8(15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1, -1, -1, -1, -1);
3720 
3721  // Mask to select the gray component
3722  const __m128i mask_low1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1);
3723  const __m128i mask_low2 = _mm_set_epi8(15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1);
3724 
3725  // Coefficients RGB to Gray
3726  // const __m128i coeff_R = _mm_set_epi8(
3727  // 54, -1, 54, -1, 54, -1, 54, -1, 54, -1, 54, -1, 54, -1, 54, -1
3728  // );
3729  // const __m128i coeff_G = _mm_set_epi8(
3730  // 183, -1, 183, -1, 183, -1, 183, -1, 183, -1, 183, -1, 183, -1,
3731  // 183, -1
3732  // );
3733  // const __m128i coeff_B = _mm_set_epi8(
3734  // 18, -1, 18, -1, 18, -1, 18, -1, 18, -1, 18, -1, 18, -1, 18, -1
3735  // );
3736  // const __m128i coeff_R = _mm_set_epi16(
3737  // 6969*2, 6969*2, 6969*2, 6969*2, 6969*2, 6969*2, 6969*2, 6969*2
3738  // );
3739  // const __m128i coeff_G = _mm_set_epi16(
3740  // 23434*2, 23434*2, 23434*2, 23434*2, 23434*2, 23434*2, 23434*2,
3741  // 23434*2
3742  // );
3743  // const __m128i coeff_B = _mm_set_epi16(
3744  // 2365*2, 2365*2, 2365*2, 2365*2, 2365*2, 2365*2, 2365*2, 2365*2
3745  // );
3746  const __m128i coeff_R = _mm_set_epi16(13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933);
3747  const __m128i coeff_G = _mm_set_epi16((short int)46871, (short int)46871, (short int)46871, (short int)46871,
3748  (short int)46871, (short int)46871, (short int)46871, (short int)46871);
3749  const __m128i coeff_B = _mm_set_epi16(4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732);
3750 
3751  if (flip) {
3752  int i = ((int)height) - 1;
3753  int lineStep = -(int)(width * 3);
3754  bgr = bgr + (width * (height - 1) * 3);
3755 
3756  unsigned char *linePtr = bgr;
3757  unsigned char r, g, b;
3758 
3759  if (width >= 16) {
3760  for (; i >= 0; i--) {
3761  unsigned int j = 0;
3762 
3763  for (; j <= width - 16; j += 16) {
3764  // Process 16 color pixels
3765  const __m128i data1 = _mm_loadu_si128((const __m128i *)bgr);
3766  const __m128i data2 = _mm_loadu_si128((const __m128i *)(bgr + 16));
3767  const __m128i data3 = _mm_loadu_si128((const __m128i *)(bgr + 32));
3768 
3769  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3770  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3771  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3772 
3773  const __m128i grays_0_7 =
3774  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3775  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3776 
3777  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4));
3778  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4));
3779  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4));
3780 
3781  const __m128i grays_8_15 =
3782  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R), _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G),
3783  _mm_mulhi_epu16(blue_8_15, coeff_B)));
3784 
3785  _mm_storeu_si128((__m128i *)grey, _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1),
3786  _mm_shuffle_epi8(grays_8_15, mask_low2)));
3787 
3788  bgr += 48;
3789  grey += 16;
3790  }
3791 
3792  for (; j < width; j++) {
3793  b = *(bgr++);
3794  g = *(bgr++);
3795  r = *(bgr++);
3796  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
3797  }
3798 
3799  linePtr += lineStep;
3800  bgr = linePtr;
3801  }
3802  }
3803 
3804  for (; i >= 0; i--) {
3805  for (unsigned int j = 0; j < width; j++) {
3806  b = *(bgr++);
3807  g = *(bgr++);
3808  r = *(bgr++);
3809  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
3810  }
3811 
3812  linePtr += lineStep;
3813  bgr = linePtr;
3814  }
3815  } else {
3816  unsigned int i = 0;
3817  unsigned int size = width * height;
3818 
3819  if (size >= 16) {
3820  for (; i <= size - 16; i += 16) {
3821  // Process 16 color pixels
3822  const __m128i data1 = _mm_loadu_si128((const __m128i *)bgr);
3823  const __m128i data2 = _mm_loadu_si128((const __m128i *)(bgr + 16));
3824  const __m128i data3 = _mm_loadu_si128((const __m128i *)(bgr + 32));
3825 
3826  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3827  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3828  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3829 
3830  const __m128i grays_0_7 =
3831  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3832  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3833 
3834  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4));
3835  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4));
3836  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4));
3837 
3838  const __m128i grays_8_15 =
3839  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R),
3840  _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G), _mm_mulhi_epu16(blue_8_15, coeff_B)));
3841 
3842  _mm_storeu_si128((__m128i *)grey, _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1),
3843  _mm_shuffle_epi8(grays_8_15, mask_low2)));
3844 
3845  bgr += 48;
3846  grey += 16;
3847  }
3848  }
3849 
3850  for (; i < size; i++) {
3851  *grey = (unsigned char)(0.2126 * (*(bgr + 2)) + 0.7152 * (*(bgr + 1)) + 0.0722 * (*bgr));
3852 
3853  bgr += 3;
3854  ++grey;
3855  }
3856  }
3857 #endif
3858  } else {
3859  // if we have to flip the image, we start from the end last scanline so
3860  // the step is negative
3861  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
3862 
3863  // starting source address = last line if we need to flip the image
3864  unsigned char *src = (flip) ? bgr + (width * height * 3) + lineStep : bgr;
3865 
3866  for (unsigned int i = 0; i < height; i++) {
3867  unsigned char *line = src;
3868  for (unsigned int j = 0; j < width; j++) {
3869  *grey++ = (unsigned char)(0.2126 * *(line + 2) + 0.7152 * *(line + 1) + 0.0722 * *(line + 0));
3870  line += 3;
3871  }
3872 
3873  // go to the next line
3874  src += lineStep;
3875  }
3876  }
3877 }
3878 
3886 void vpImageConvert::RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int width, unsigned int height,
3887  bool flip)
3888 {
3889  // if we have to flip the image, we start from the end last scanline so the
3890  // step is negative
3891  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
3892 
3893  // starting source address = last line if we need to flip the image
3894  unsigned char *src = (flip) ? (rgb + (width * height * 3) + lineStep) : rgb;
3895 
3896  unsigned int j = 0;
3897  unsigned int i = 0;
3898 
3899  for (i = 0; i < height; i++) {
3900  unsigned char *line = src;
3901  for (j = 0; j < width; j++) {
3902  *rgba++ = *(line++);
3903  *rgba++ = *(line++);
3904  *rgba++ = *(line++);
3905  *rgba++ = vpRGBa::alpha_default;
3906  }
3907  // go to the next line
3908  src += lineStep;
3909  }
3910 }
3911 
3917 void vpImageConvert::RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height,
3918  bool flip)
3919 {
3920  if (flip) {
3921  bool checkSSSE3 = vpCPUFeatures::checkSSSE3();
3922 #if !VISP_HAVE_SSSE3
3923  checkSSSE3 = false;
3924 #endif
3925 
3926  if (checkSSSE3) {
3927 #if VISP_HAVE_SSSE3
3928  int i = ((int)height) - 1;
3929  int lineStep = -(int)(width * 3);
3930  rgb = rgb + (width * (height - 1) * 3);
3931 
3932  unsigned char *linePtr = rgb;
3933  unsigned char r, g, b;
3934 
3935  if (width >= 16) {
3936  // Mask to select R component
3937  const __m128i mask_R1 = _mm_set_epi8(-1, -1, -1, -1, 15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1);
3938  const __m128i mask_R2 = _mm_set_epi8(5, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3939  const __m128i mask_R3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1);
3940  const __m128i mask_R4 = _mm_set_epi8(13, -1, 10, -1, 7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1);
3941 
3942  // Mask to select G component
3943  const __m128i mask_G1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 13, -1, 10, -1, 7, -1, 4, -1, 1, -1);
3944  const __m128i mask_G2 = _mm_set_epi8(6, -1, 3, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3945  const __m128i mask_G3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 12, -1, 9, -1);
3946  const __m128i mask_G4 = _mm_set_epi8(14, -1, 11, -1, 8, -1, 5, -1, 2, -1, -1, -1, -1, -1, -1, -1);
3947 
3948  // Mask to select B component
3949  const __m128i mask_B1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1, 5, -1, 2, -1);
3950  const __m128i mask_B2 = _mm_set_epi8(7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
3951  const __m128i mask_B3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 10, -1);
3952  const __m128i mask_B4 = _mm_set_epi8(15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1, -1, -1, -1, -1);
3953 
3954  // Mask to select the gray component
3955  const __m128i mask_low1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1);
3956  const __m128i mask_low2 = _mm_set_epi8(15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1);
3957 
3958  // Coefficients RGB to Gray
3959  const __m128i coeff_R = _mm_set_epi16(13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933);
3960  const __m128i coeff_G = _mm_set_epi16((short int)46871, (short int)46871, (short int)46871, (short int)46871,
3961  (short int)46871, (short int)46871, (short int)46871, (short int)46871);
3962  const __m128i coeff_B = _mm_set_epi16(4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732);
3963 
3964  for (; i >= 0; i--) {
3965  unsigned int j = 0;
3966 
3967  for (; j <= width - 16; j += 16) {
3968  // Process 16 color pixels
3969  const __m128i data1 = _mm_loadu_si128((const __m128i *)rgb);
3970  const __m128i data2 = _mm_loadu_si128((const __m128i *)(rgb + 16));
3971  const __m128i data3 = _mm_loadu_si128((const __m128i *)(rgb + 32));
3972 
3973  const __m128i red_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2));
3974  const __m128i green_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2));
3975  const __m128i blue_0_7 = _mm_or_si128(_mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2));
3976 
3977  const __m128i grays_0_7 =
3978  _mm_adds_epu16(_mm_mulhi_epu16(red_0_7, coeff_R),
3979  _mm_adds_epu16(_mm_mulhi_epu16(green_0_7, coeff_G), _mm_mulhi_epu16(blue_0_7, coeff_B)));
3980 
3981  const __m128i red_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4));
3982  const __m128i green_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4));
3983  const __m128i blue_8_15 = _mm_or_si128(_mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4));
3984 
3985  const __m128i grays_8_15 =
3986  _mm_adds_epu16(_mm_mulhi_epu16(red_8_15, coeff_R), _mm_adds_epu16(_mm_mulhi_epu16(green_8_15, coeff_G),
3987  _mm_mulhi_epu16(blue_8_15, coeff_B)));
3988 
3989  _mm_storeu_si128((__m128i *)grey, _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1),
3990  _mm_shuffle_epi8(grays_8_15, mask_low2)));
3991 
3992  rgb += 48;
3993  grey += 16;
3994  }
3995 
3996  for (; j < width; j++) {
3997  r = *(rgb++);
3998  g = *(rgb++);
3999  b = *(rgb++);
4000  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
4001  }
4002 
4003  linePtr += lineStep;
4004  rgb = linePtr;
4005  }
4006  }
4007 
4008  for (; i >= 0; i--) {
4009  for (unsigned int j = 0; j < width; j++) {
4010  r = *(rgb++);
4011  g = *(rgb++);
4012  b = *(rgb++);
4013  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
4014  }
4015 
4016  linePtr += lineStep;
4017  rgb = linePtr;
4018  }
4019 #endif
4020  } else {
4021  // if we have to flip the image, we start from the end last scanline so
4022  // the step is negative
4023  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
4024 
4025  // starting source address = last line if we need to flip the image
4026  unsigned char *src = (flip) ? rgb + (width * height * 3) + lineStep : rgb;
4027 
4028  unsigned int j = 0;
4029  unsigned int i = 0;
4030 
4031  unsigned r, g, b;
4032 
4033  for (i = 0; i < height; i++) {
4034  unsigned char *line = src;
4035  for (j = 0; j < width; j++) {
4036  r = *(line++);
4037  g = *(line++);
4038  b = *(line++);
4039  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
4040  }
4041 
4042  // go to the next line
4043  src += lineStep;
4044  }
4045  }
4046  } else {
4047  RGBToGrey(rgb, grey, width * height);
4048  }
4049 }
4050 
4054 void vpImageConvert::computeYCbCrLUT()
4055 {
4056  if (YCbCrLUTcomputed == false) {
4057  int index = 256;
4058 
4059  while (index--) {
4060 
4061  int aux = index - 128;
4062  vpImageConvert::vpCrr[index] = (int)(364.6610 * aux) >> 8;
4063  vpImageConvert::vpCgb[index] = (int)(-89.8779 * aux) >> 8;
4064  vpImageConvert::vpCgr[index] = (int)(-185.8154 * aux) >> 8;
4065  vpImageConvert::vpCbb[index] = (int)(460.5724 * aux) >> 8;
4066  }
4067 
4068  YCbCrLUTcomputed = true;
4069  }
4070 }
4071 
4091 void vpImageConvert::YCbCrToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
4092 {
4093  unsigned char *cbv;
4094  unsigned char *crv;
4095  unsigned char *pt_ycbcr = ycbcr;
4096  unsigned char *pt_rgb = rgb;
4097  cbv = pt_ycbcr + 1;
4098  crv = pt_ycbcr + 3;
4099 
4100  vpImageConvert::computeYCbCrLUT();
4101 
4102  int col = 0;
4103 
4104  while (size--) {
4105  int val_r, val_g, val_b;
4106  if (!(col++ % 2)) {
4107  cbv = pt_ycbcr + 1;
4108  crv = pt_ycbcr + 3;
4109  }
4110 
4111  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4112  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4113  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4114 
4115  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4116 
4117  *pt_rgb++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4118  *pt_rgb++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4119  *pt_rgb++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4120 
4121  pt_ycbcr += 2;
4122  }
4123 }
4124 
4148 void vpImageConvert::YCbCrToRGBa(unsigned char *ycbcr, unsigned char *rgba, unsigned int size)
4149 {
4150  unsigned char *cbv;
4151  unsigned char *crv;
4152  unsigned char *pt_ycbcr = ycbcr;
4153  unsigned char *pt_rgba = rgba;
4154  cbv = pt_ycbcr + 1;
4155  crv = pt_ycbcr + 3;
4156 
4157  vpImageConvert::computeYCbCrLUT();
4158 
4159  int col = 0;
4160 
4161  while (size--) {
4162  int val_r, val_g, val_b;
4163  if (!(col++ % 2)) {
4164  cbv = pt_ycbcr + 1;
4165  crv = pt_ycbcr + 3;
4166  }
4167 
4168  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4169  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4170  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4171 
4172  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4173 
4174  *pt_rgba++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4175  *pt_rgba++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4176  *pt_rgba++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4177  *pt_rgba++ = vpRGBa::alpha_default;
4178 
4179  pt_ycbcr += 2;
4180  }
4181 }
4182 
4199 void vpImageConvert::YCbCrToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
4200 {
4201  unsigned int i = 0, j = 0;
4202 
4203  while (j < size * 2) {
4204  grey[i++] = yuv[j];
4205  grey[i++] = yuv[j + 2];
4206  j += 4;
4207  }
4208 }
4209 
4228 void vpImageConvert::YCrCbToRGB(unsigned char *ycrcb, unsigned char *rgb, unsigned int size)
4229 {
4230  unsigned char *cbv;
4231  unsigned char *crv;
4232  unsigned char *pt_ycbcr = ycrcb;
4233  unsigned char *pt_rgb = rgb;
4234  crv = pt_ycbcr + 1;
4235  cbv = pt_ycbcr + 3;
4236 
4237  vpImageConvert::computeYCbCrLUT();
4238 
4239  int col = 0;
4240 
4241  while (size--) {
4242  int val_r, val_g, val_b;
4243  if (!(col++ % 2)) {
4244  crv = pt_ycbcr + 1;
4245  cbv = pt_ycbcr + 3;
4246  }
4247 
4248  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4249  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4250  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4251 
4252  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4253 
4254  *pt_rgb++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4255  *pt_rgb++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4256  *pt_rgb++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4257 
4258  pt_ycbcr += 2;
4259  }
4260 }
4283 void vpImageConvert::YCrCbToRGBa(unsigned char *ycrcb, unsigned char *rgba, unsigned int size)
4284 {
4285  unsigned char *cbv;
4286  unsigned char *crv;
4287  unsigned char *pt_ycbcr = ycrcb;
4288  unsigned char *pt_rgba = rgba;
4289  crv = pt_ycbcr + 1;
4290  cbv = pt_ycbcr + 3;
4291 
4292  vpImageConvert::computeYCbCrLUT();
4293 
4294  int col = 0;
4295 
4296  while (size--) {
4297  int val_r, val_g, val_b;
4298  if (!(col++ % 2)) {
4299  crv = pt_ycbcr + 1;
4300  cbv = pt_ycbcr + 3;
4301  }
4302 
4303  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4304  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4305  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4306 
4307  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4308 
4309  *pt_rgba++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4310  *pt_rgba++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4311  *pt_rgba++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4312  *pt_rgba++ = vpRGBa::alpha_default;
4313 
4314  pt_ycbcr += 2;
4315  }
4316 }
4317 
4355 {
4356  size_t n = src.getNumberOfPixel();
4357  unsigned int height = src.getHeight();
4358  unsigned int width = src.getWidth();
4359  unsigned char *input;
4360  unsigned char *dst;
4361 
4362  vpImage<unsigned char> *tabChannel[4];
4363 
4364  /* incrsrc[0] = 0; //init
4365  incrsrc[1] = 0; //step after the first used channel
4366  incrsrc[2] = 0; //step after the second used channel
4367  incrsrc[3] = 0;
4368  incrsrc[4] = 0;
4369  */
4370  tabChannel[0] = pR;
4371  tabChannel[1] = pG;
4372  tabChannel[2] = pB;
4373  tabChannel[3] = pa;
4374 
4375  size_t i; /* ordre */
4376  for (unsigned int j = 0; j < 4; j++) {
4377  if (tabChannel[j] != NULL) {
4378  if (tabChannel[j]->getHeight() != height || tabChannel[j]->getWidth() != width) {
4379  tabChannel[j]->resize(height, width);
4380  }
4381  dst = (unsigned char *)tabChannel[j]->bitmap;
4382 
4383  input = (unsigned char *)src.bitmap + j;
4384  i = 0;
4385 #if 1 // optimization
4386  if (n >= 4) { /* boucle deroulee lsize fois */
4387  n -= 3;
4388  for (; i < n; i += 4) {
4389  *dst = *input;
4390  input += 4;
4391  dst++;
4392  *dst = *input;
4393  input += 4;
4394  dst++;
4395  *dst = *input;
4396  input += 4;
4397  dst++;
4398  *dst = *input;
4399  input += 4;
4400  dst++;
4401  }
4402  n += 3;
4403  }
4404 #endif
4405  for (; i < n; i++) {
4406  *dst = *input;
4407  input += 4;
4408  dst++;
4409  }
4410  }
4411  }
4412 }
4413 
4424 {
4425  // Check if the input channels have all the same dimensions
4426  std::map<unsigned int, unsigned int> mapOfWidths, mapOfHeights;
4427  if (R != NULL) {
4428  mapOfWidths[R->getWidth()]++;
4429  mapOfHeights[R->getHeight()]++;
4430  }
4431 
4432  if (G != NULL) {
4433  mapOfWidths[G->getWidth()]++;
4434  mapOfHeights[G->getHeight()]++;
4435  }
4436 
4437  if (B != NULL) {
4438  mapOfWidths[B->getWidth()]++;
4439  mapOfHeights[B->getHeight()]++;
4440  }
4441 
4442  if (a != NULL) {
4443  mapOfWidths[a->getWidth()]++;
4444  mapOfHeights[a->getHeight()]++;
4445  }
4446 
4447  if (mapOfWidths.size() == 1 && mapOfHeights.size() == 1) {
4448  unsigned int width = mapOfWidths.begin()->first;
4449  unsigned int height = mapOfHeights.begin()->first;
4450 
4451  RGBa.resize(height, width);
4452 
4453  unsigned int size = width * height;
4454  for (unsigned int i = 0; i < size; i++) {
4455  if (R != NULL) {
4456  RGBa.bitmap[i].R = R->bitmap[i];
4457  }
4458 
4459  if (G != NULL) {
4460  RGBa.bitmap[i].G = G->bitmap[i];
4461  }
4462 
4463  if (B != NULL) {
4464  RGBa.bitmap[i].B = B->bitmap[i];
4465  }
4466 
4467  if (a != NULL) {
4468  RGBa.bitmap[i].A = a->bitmap[i];
4469  }
4470  }
4471  } else {
4472  throw vpException(vpException::dimensionError, "Mismatch dimensions !");
4473  }
4474 }
4475 
4486 void vpImageConvert::MONO16ToGrey(unsigned char *grey16, unsigned char *grey, unsigned int size)
4487 {
4488  int i = (((int)size) << 1) - 1;
4489  int j = (int)size - 1;
4490 
4491  while (i >= 0) {
4492  int y = grey16[i--];
4493  grey[j--] = static_cast<unsigned char>((y + (grey16[i--] << 8)) >> 8);
4494  }
4495 }
4496 
4509 void vpImageConvert::MONO16ToRGBa(unsigned char *grey16, unsigned char *rgba, unsigned int size)
4510 {
4511  int i = (((int)size) << 1) - 1;
4512  int j = (int)(size * 4 - 1);
4513 
4514  while (i >= 0) {
4515  int y = grey16[i--];
4516  unsigned char v = static_cast<unsigned char>((y + (grey16[i--] << 8)) >> 8);
4517  rgba[j--] = vpRGBa::alpha_default;
4518  rgba[j--] = v;
4519  rgba[j--] = v;
4520  rgba[j--] = v;
4521  }
4522 }
4523 
4524 void vpImageConvert::HSV2RGB(const double *hue_, const double *saturation_, const double *value_, unsigned char *rgb,
4525  unsigned int size, unsigned int step)
4526 {
4527  for (unsigned int i = 0; i < size; i++) {
4528  double hue = hue_[i], saturation = saturation_[i], value = value_[i];
4529 
4530  if (vpMath::equal(saturation, 0.0, std::numeric_limits<double>::epsilon())) {
4531  hue = value;
4532  saturation = value;
4533  } else {
4534  double h = hue * 6.0;
4535  double s = saturation;
4536  double v = value;
4537 
4538  if (vpMath::equal(h, 6.0, std::numeric_limits<double>::epsilon())) {
4539  h = 0.0;
4540  }
4541 
4542  double f = h - (int)h;
4543  double p = v * (1.0 - s);
4544  double q = v * (1.0 - s * f);
4545  double t = v * (1.0 - s * (1.0 - f));
4546 
4547  switch ((int)h) {
4548  case 0:
4549  hue = v;
4550  saturation = t;
4551  value = p;
4552  break;
4553 
4554  case 1:
4555  hue = q;
4556  saturation = v;
4557  value = p;
4558  break;
4559 
4560  case 2:
4561  hue = p;
4562  saturation = v;
4563  value = t;
4564  break;
4565 
4566  case 3:
4567  hue = p;
4568  saturation = q;
4569  value = v;
4570  break;
4571 
4572  case 4:
4573  hue = t;
4574  saturation = p;
4575  value = v;
4576  break;
4577 
4578  default: // case 5:
4579  hue = v;
4580  saturation = p;
4581  value = q;
4582  break;
4583  }
4584  }
4585 
4586  rgb[i * step] = (unsigned char)vpMath::round(hue * 255.0);
4587  rgb[i * step + 1] = (unsigned char)vpMath::round(saturation * 255.0);
4588  rgb[i * step + 2] = (unsigned char)vpMath::round(value * 255.0);
4589  if (step == 4) // alpha
4590  rgb[i * step + 3] = vpRGBa::alpha_default;
4591  }
4592 }
4593 
4594 void vpImageConvert::RGB2HSV(const unsigned char *rgb, double *hue, double *saturation, double *value,
4595  unsigned int size, unsigned int step)
4596 {
4597  for (unsigned int i = 0; i < size; i++) {
4598  double red, green, blue;
4599  double h, s, v;
4600  double min, max;
4601 
4602  red = rgb[i * step] / 255.0;
4603  green = rgb[i * step + 1] / 255.0;
4604  blue = rgb[i * step + 2] / 255.0;
4605 
4606  if (red > green) {
4607  max = ((std::max))(red, blue);
4608  min = ((std::min))(green, blue);
4609  } else {
4610  max = ((std::max))(green, blue);
4611  min = ((std::min))(red, blue);
4612  }
4613 
4614  v = max;
4615 
4616  if (!vpMath::equal(max, 0.0, std::numeric_limits<double>::epsilon())) {
4617  s = (max - min) / max;
4618  } else {
4619  s = 0.0;
4620  }
4621 
4622  if (vpMath::equal(s, 0.0, std::numeric_limits<double>::epsilon())) {
4623  h = 0.0;
4624  } else {
4625  double delta = max - min;
4626  if (vpMath::equal(delta, 0.0, std::numeric_limits<double>::epsilon())) {
4627  delta = 1.0;
4628  }
4629 
4630  if (vpMath::equal(red, max, std::numeric_limits<double>::epsilon())) {
4631  h = (green - blue) / delta;
4632  } else if (vpMath::equal(green, max, std::numeric_limits<double>::epsilon())) {
4633  h = 2 + (blue - red) / delta;
4634  } else {
4635  h = 4 + (red - green) / delta;
4636  }
4637 
4638  h /= 6.0;
4639  if (h < 0.0) {
4640  h += 1.0;
4641  } else if (h > 1.0) {
4642  h -= 1.0;
4643  }
4644  }
4645 
4646  hue[i] = h;
4647  saturation[i] = s;
4648  value[i] = v;
4649  }
4650 }
4651 
4664 void vpImageConvert::HSVToRGBa(const double *hue, const double *saturation, const double *value, unsigned char *rgba,
4665  unsigned int size)
4666 {
4667  vpImageConvert::HSV2RGB(hue, saturation, value, rgba, size, 4);
4668 }
4669 
4682 void vpImageConvert::HSVToRGBa(const unsigned char *hue, const unsigned char *saturation, const unsigned char *value,
4683  unsigned char *rgba, unsigned int size)
4684 {
4685  for (unsigned int i = 0; i < size; i++) {
4686  double h = hue[i] / 255.0, s = saturation[i] / 255.0, v = value[i] / 255.0;
4687 
4688  vpImageConvert::HSVToRGBa(&h, &s, &v, (rgba + i * 4), 1);
4689  }
4690 }
4691 
4703 void vpImageConvert::RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value,
4704  unsigned int size)
4705 {
4706  vpImageConvert::RGB2HSV(rgba, hue, saturation, value, size, 4);
4707 }
4708 
4720 void vpImageConvert::RGBaToHSV(const unsigned char *rgba, unsigned char *hue, unsigned char *saturation,
4721  unsigned char *value, unsigned int size)
4722 {
4723  for (unsigned int i = 0; i < size; i++) {
4724  double h, s, v;
4725  vpImageConvert::RGBaToHSV((rgba + i * 4), &h, &s, &v, 1);
4726 
4727  hue[i] = (unsigned char)(255.0 * h);
4728  saturation[i] = (unsigned char)(255.0 * s);
4729  value[i] = (unsigned char)(255.0 * v);
4730  }
4731 }
4732 
4742 void vpImageConvert::HSVToRGB(const double *hue, const double *saturation, const double *value, unsigned char *rgb,
4743  unsigned int size)
4744 {
4745  vpImageConvert::HSV2RGB(hue, saturation, value, rgb, size, 3);
4746 }
4747 
4757 void vpImageConvert::HSVToRGB(const unsigned char *hue, const unsigned char *saturation, const unsigned char *value,
4758  unsigned char *rgb, unsigned int size)
4759 {
4760  for (unsigned int i = 0; i < size; i++) {
4761  double h = hue[i] / 255.0, s = saturation[i] / 255.0, v = value[i] / 255.0;
4762 
4763  vpImageConvert::HSVToRGB(&h, &s, &v, (rgb + i * 3), 1);
4764  }
4765 }
4766 
4777 void vpImageConvert::RGBToHSV(const unsigned char *rgb, double *hue, double *saturation, double *value,
4778  unsigned int size)
4779 {
4780  vpImageConvert::RGB2HSV(rgb, hue, saturation, value, size, 3);
4781 }
4782 
4793 void vpImageConvert::RGBToHSV(const unsigned char *rgb, unsigned char *hue, unsigned char *saturation,
4794  unsigned char *value, unsigned int size)
4795 {
4796  for (unsigned int i = 0; i < size; i++) {
4797  double h, s, v;
4798 
4799  vpImageConvert::RGBToHSV((rgb + i * 3), &h, &s, &v, 1);
4800 
4801  hue[i] = (unsigned char)(255.0 * h);
4802  saturation[i] = (unsigned char)(255.0 * s);
4803  value[i] = (unsigned char)(255.0 * v);
4804  }
4805 }
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)
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:881
static void HSVToRGB(const double *hue, const double *saturation, const double *value, unsigned char *rgb, unsigned int size)
unsigned char B
Blue component.
Definition: vpRGBa.h:150
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
unsigned int getRows() const
Definition: vpImage.h:218
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false)
static void RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value, unsigned int size)
Type * bitmap
points toward the bitmap
Definition: vpImage.h:143
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:300
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 void RGBToHSV(const unsigned char *rgb, double *hue, double *saturation, double *value, unsigned int size)
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)
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)
static void YCbCrToGrey(unsigned char *ycbcr, unsigned char *grey, unsigned int size)
unsigned int getCols() const
Definition: vpImage.h:179
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)
VISP_EXPORT bool checkSSSE3()
static void HSVToRGBa(const double *hue, const double *saturation, const double *value, unsigned char *rgba, unsigned int size)
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)
unsigned int getNumberOfPixel() const
Definition: vpImage.h:209
static int round(double x)
Definition: vpMath.h:245
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)
unsigned int getHeight() const
Definition: vpImage.h:188
static void YUV411ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
unsigned int getSize() const
Definition: vpImage.h:227
unsigned char R
Red component.
Definition: vpRGBa.h:148
#define vpDEBUG_TRACE
Definition: vpDebug.h:487
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 YCrCbToRGBa(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
unsigned int getWidth() const
Definition: vpImage.h:246
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)
void getMinMaxValue(Type &min, Type &max) const
Look for the minimum and the maximum value within the bitmap.
Definition: vpImage.h:1019
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)