Visual Servoing Platform  version 3.6.1 under development (2024-03-18)
vpImageConvert.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 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 https://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 *****************************************************************************/
35 
41 #include <map>
42 #include <sstream>
43 
44 #if defined(_OPENMP)
45 #include <omp.h>
46 #endif
47 
48 
49 #include <visp3/core/vpConfig.h>
50 // image
51 #include "private/vpBayerConversion.h"
52 #include "private/vpImageConvert_impl.h"
53 #if defined(VISP_HAVE_SIMDLIB)
54 #include <Simd/SimdLib.h>
55 #endif
56 #include <visp3/core/vpImageConvert.h>
57 
58 bool vpImageConvert::YCbCrLUTcomputed = false;
59 int vpImageConvert::vpCrr[256];
60 int vpImageConvert::vpCgb[256];
61 int vpImageConvert::vpCgr[256];
62 int vpImageConvert::vpCbb[256];
63 
73 {
74  dest.resize(src.getHeight(), src.getWidth());
75 
76  GreyToRGBa(src.bitmap, reinterpret_cast<unsigned char *>(dest.bitmap), src.getWidth(), src.getHeight());
77 }
78 
88 void vpImageConvert::convert(const vpImage<vpRGBa> &src, vpImage<unsigned char> &dest, unsigned int nThreads)
89 {
90  dest.resize(src.getHeight(), src.getWidth());
91 
92  RGBaToGrey(reinterpret_cast<unsigned char *>(src.bitmap), dest.bitmap, src.getWidth(), src.getHeight(), nThreads);
93 }
94 
102 {
103  dest.resize(src.getHeight(), src.getWidth());
104  unsigned int max_xy = src.getWidth() * src.getHeight();
105  float min, max;
106 
107  src.getMinMaxValue(min, max);
108 
109  for (unsigned int i = 0; i < max_xy; ++i) {
110  float val = 255.f * ((src.bitmap[i] - min) / (max - min));
111  if (val < 0) {
112  dest.bitmap[i] = 0;
113  }
114  else if (val > 255) {
115  dest.bitmap[i] = 255;
116  }
117  else {
118  dest.bitmap[i] = static_cast<unsigned char>(val);
119  }
120  }
121 }
122 
130 {
131  const unsigned int srcHeight = src.getHeight(), srcWidth = src.getWidth();
132  dest.resize(src.getHeight(), src.getWidth());
133  vpRGBf min, max;
134  src.getMinMaxValue(min, max);
135 
136  for (unsigned int i = 0; i < srcHeight; ++i) {
137  for (unsigned int j = 0; j < srcWidth; ++j) {
138  for (unsigned int c = 0; c < 3; ++c) {
139  float val = 255.f * ((reinterpret_cast<const float *>(&(src[i][j]))[c] - reinterpret_cast<float *>(&min)[c]) /
140  (reinterpret_cast<float *>(&max)[c] - reinterpret_cast<float *>(&min)[c]));
141  if (val < 0) {
142  reinterpret_cast<unsigned char *>(&(dest[i][j]))[c] = 0;
143  }
144  else if (val > 255) {
145  reinterpret_cast<unsigned char *>(&(dest[i][j]))[c] = 255;
146  }
147  else {
148  reinterpret_cast<unsigned char *>(&(dest[i][j]))[c] = static_cast<unsigned char>(val);
149  }
150  }
151  }
152  }
153 }
154 
161 {
162  const unsigned int srcHeight = src.getHeight(), srcWidth = src.getWidth();
163  const unsigned int srcSize = srcHeight * srcWidth;
164  dest.resize(srcHeight, srcWidth);
165  for (unsigned int i = 0; i < srcSize; ++i) {
166  dest.bitmap[i] = static_cast<float>(src.bitmap[i]);
167  }
168 }
169 
177 {
178  dest.resize(src.getHeight(), src.getWidth());
179  unsigned int max_xy = src.getWidth() * src.getHeight();
180  double min, max;
181 
182  src.getMinMaxValue(min, max);
183 
184  for (unsigned int i = 0; i < max_xy; ++i) {
185  double val = 255. * ((src.bitmap[i] - min) / (max - min));
186  if (val < 0) {
187  dest.bitmap[i] = 0;
188  }
189  else if (val > 255) {
190  dest.bitmap[i] = 255;
191  }
192  else {
193  dest.bitmap[i] = static_cast<unsigned char>(val);
194  }
195  }
196 }
197 
204 void vpImageConvert::convert(const vpImage<uint16_t> &src, vpImage<unsigned char> &dest, unsigned char bitshift)
205 {
206  const unsigned int srcSize = src.getSize();
207  dest.resize(src.getHeight(), src.getWidth());
208 
209  for (unsigned int i = 0; i < srcSize; ++i) {
210  dest.bitmap[i] = static_cast<unsigned char>(src.bitmap[i] >> bitshift);
211  }
212 }
213 
220 void vpImageConvert::convert(const vpImage<unsigned char> &src, vpImage<uint16_t> &dest, unsigned char bitshift)
221 {
222  const unsigned int srcSize = src.getSize();
223  dest.resize(src.getHeight(), src.getWidth());
224 
225  for (unsigned int i = 0; i < srcSize; ++i) {
226  dest.bitmap[i] = static_cast<unsigned char>(src.bitmap[i] << bitshift);
227  }
228 }
229 
236 {
237  const unsigned int srcHeight = src.getHeight(), srcWidth = src.getWidth();
238  const unsigned int srcSize = srcHeight * srcWidth;
239  dest.resize(srcHeight, srcWidth);
240  for (unsigned int i = 0; i < srcSize; ++i) {
241  dest.bitmap[i] = static_cast<double>(src.bitmap[i]);
242  }
243 }
244 
253 {
254  vp_createDepthHistogram(src_depth, dest_rgba);
255 }
256 
264 {
265  vp_createDepthHistogram(src_depth, dest_depth);
266 }
267 
276 {
277  vp_createDepthHistogram(src_depth, dest_rgba);
278 }
279 
287 {
288  vp_createDepthHistogram(src_depth, dest_depth);
289 }
290 
291 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
292 
333 void vpImageConvert::convert(const cv::Mat &src, vpImage<vpRGBa> &dest, bool flip)
334 {
335  dest.resize(static_cast<unsigned int>(src.rows), static_cast<unsigned int>(src.cols));
336  unsigned int destRows = dest.getRows();
337  unsigned int destCols = dest.getCols();
338  if (src.type() == CV_8UC4) {
339  vpRGBa rgbaVal;
340  for (unsigned int i = 0; i < destRows; ++i)
341  for (unsigned int j = 0; j < destCols; ++j) {
342  cv::Vec4b tmp = src.at<cv::Vec4b>(static_cast<int>(i), static_cast<int>(j));
343  rgbaVal.R = tmp[2];
344  rgbaVal.G = tmp[1];
345  rgbaVal.B = tmp[0];
346  rgbaVal.A = tmp[3];
347  if (flip) {
348  dest[destRows - i - 1][j] = rgbaVal;
349  }
350  else {
351  dest[i][j] = rgbaVal;
352  }
353  }
354  }
355  else if (src.type() == CV_8UC3) {
356 #if defined(VISP_HAVE_SIMDLIB)
357  if (src.isContinuous() && (!flip)) {
358  SimdRgbToBgra(src.data, src.cols, src.rows, src.step[0], reinterpret_cast<uint8_t *>(dest.bitmap),
359  dest.getWidth() * sizeof(vpRGBa), vpRGBa::alpha_default);
360  }
361  else {
362 #endif
363  vpRGBa rgbaVal;
364  rgbaVal.A = vpRGBa::alpha_default;
365  for (unsigned int i = 0; i < destRows; ++i) {
366  for (unsigned int j = 0; j < destCols; ++j) {
367  cv::Vec3b tmp = src.at<cv::Vec3b>(static_cast<int>(i), static_cast<int>(j));
368  rgbaVal.R = tmp[2];
369  rgbaVal.G = tmp[1];
370  rgbaVal.B = tmp[0];
371  if (flip) {
372  dest[destRows - i - 1][j] = rgbaVal;
373  }
374  else {
375  dest[i][j] = rgbaVal;
376  }
377  }
378  }
379 #if defined(VISP_HAVE_SIMDLIB)
380  }
381 #endif
382  }
383  else if (src.type() == CV_8UC1) {
384 #if defined(VISP_HAVE_SIMDLIB)
385  if (src.isContinuous() && (!flip)) {
386  SimdGrayToBgra(src.data, src.cols, src.rows, src.step[0], reinterpret_cast<uint8_t *>(dest.bitmap),
387  dest.getWidth() * sizeof(vpRGBa), vpRGBa::alpha_default);
388  }
389  else {
390 #endif
391  vpRGBa rgbaVal;
392  for (unsigned int i = 0; i < destRows; ++i) {
393  for (unsigned int j = 0; j < destCols; ++j) {
394  rgbaVal = src.at<unsigned char>(static_cast<int>(i), static_cast<int>(j));
395  rgbaVal.A = vpRGBa::alpha_default;
396  if (flip) {
397  dest[destRows - i - 1][j] = rgbaVal;
398  }
399  else {
400  dest[i][j] = rgbaVal;
401  }
402  }
403  }
404 #if defined(VISP_HAVE_SIMDLIB)
405  }
406 #endif
407  }
408 }
409 
445 void vpImageConvert::convert(const cv::Mat &src, vpImage<unsigned char> &dest, bool flip, unsigned int nThreads)
446 {
447  if (src.type() == CV_8UC1) {
448  dest.resize(static_cast<unsigned int>(src.rows), static_cast<unsigned int>(src.cols));
449  unsigned int destRows = dest.getRows();
450  unsigned int destCols = dest.getCols();
451  if (src.isContinuous() && (!flip)) {
452  memcpy(dest.bitmap, src.data, static_cast<size_t>(src.rows * src.cols));
453  }
454  else {
455  if (flip) {
456  for (unsigned int i = 0; i < destRows; ++i) {
457  memcpy(dest.bitmap + (i * destCols), src.data + ((destRows - i - 1) * src.step1()), static_cast<size_t>(src.step));
458  }
459  }
460  else {
461  for (unsigned int i = 0; i < destRows; ++i) {
462  memcpy(dest.bitmap + (i * destCols), src.data + (i * src.step1()), static_cast<size_t>(src.step));
463  }
464  }
465  }
466  }
467  else if (src.type() == CV_8UC3) {
468  dest.resize(static_cast<unsigned int>(src.rows), static_cast<unsigned int>(src.cols));
469  unsigned int destRows = dest.getRows();
470  unsigned int destCols = dest.getCols();
471  if (src.isContinuous()) {
472  BGRToGrey((unsigned char *)src.data, (unsigned char *)dest.bitmap, static_cast<unsigned int>(src.cols), static_cast<unsigned int>(src.rows),
473  flip, nThreads);
474  }
475  else {
476  if (flip) {
477  for (unsigned int i = 0; i < destRows; ++i) {
478  BGRToGrey((unsigned char *)src.data + (i * src.step1()),
479  (unsigned char *)dest.bitmap + ((destRows - i - 1) * destCols),
480  static_cast<unsigned int>(destCols), 1, false);
481  }
482  }
483  else {
484  for (unsigned int i = 0; i < destRows; ++i) {
485  BGRToGrey((unsigned char *)src.data + (i * src.step1()), (unsigned char *)dest.bitmap + (i * destCols),
486  static_cast<unsigned int>(destCols), 1, false);
487  }
488  }
489  }
490  }
491  else if (src.type() == CV_8UC4) {
492  dest.resize(static_cast<unsigned int>(src.rows), static_cast<unsigned int>(src.cols));
493  unsigned int destRows = dest.getRows();
494  unsigned int destCols = dest.getCols();
495  if (src.isContinuous()) {
496  BGRaToGrey((unsigned char *)src.data, (unsigned char *)dest.bitmap, static_cast<unsigned int>(src.cols),
497  static_cast<unsigned int>(src.rows), flip, nThreads);
498  }
499  else {
500  if (flip) {
501  for (unsigned int i = 0; i < destRows; ++i) {
502  BGRaToGrey((unsigned char *)src.data + (i * src.step1()),
503  (unsigned char *)dest.bitmap + ((destRows - i - 1) * destCols),
504  static_cast<unsigned int>(destCols), 1, false);
505  }
506  }
507  else {
508  for (unsigned int i = 0; i < destRows; ++i) {
509  BGRaToGrey((unsigned char *)src.data + (i * src.step1()), (unsigned char *)dest.bitmap + (i * destCols),
510  static_cast<unsigned int>(destCols), 1, false);
511  }
512  }
513  }
514  }
515 }
516 
524 void vpImageConvert::convert(const cv::Mat &src, vpImage<float> &dest, bool flip)
525 {
526  dest.resize(static_cast<unsigned int>(src.rows), static_cast<unsigned int>(src.cols));
527  unsigned int destRows = dest.getRows();
528  unsigned int destCols = dest.getCols();
529 
530  if (src.type() == CV_32FC1) {
531  for (unsigned int i = 0; i < destRows; ++i)
532  for (unsigned int j = 0; j < destCols; ++j) {
533  if (flip) {
534  dest[dest.getRows() - i - 1][j] = src.at<float>(static_cast<int>(i), static_cast<int>(j));
535  }
536  else {
537  dest[i][j] = src.at<float>(static_cast<int>(i), static_cast<int>(j));
538  }
539  }
540  }
541  else {
542  throw vpException(vpException::badValue, "cv::Mat type is not supported!");
543  }
544 }
545 
553 void vpImageConvert::convert(const cv::Mat &src, vpImage<double> &dest, bool flip)
554 {
555  vpImage<float> I_float;
556  convert(src, I_float, flip);
557  unsigned int nbRows = static_cast<unsigned int>(src.rows);
558  unsigned int nbCols = static_cast<unsigned int>(src.cols);
559  dest.resize(nbRows, nbCols);
560  for (unsigned int i = 0; i < nbRows; ++i) {
561  for (unsigned int j = 0; j < nbCols; ++j) {
562  dest[i][j] = I_float[i][j];
563  }
564  }
565 }
566 
574 void vpImageConvert::convert(const cv::Mat &src, vpImage<uint16_t> &dest, bool flip)
575 {
576  dest.resize(static_cast<unsigned int>(src.rows), static_cast<unsigned int>(src.cols));
577  unsigned int destRows = dest.getRows();
578  unsigned int destCols = dest.getCols();
579 
580  if (src.type() == CV_16UC1) {
581  if (src.isContinuous()) {
582  memcpy(dest.bitmap, src.data, static_cast<size_t>(src.rows * src.cols) * sizeof(uint16_t));
583  }
584  else {
585  if (flip) {
586  for (unsigned int i = 0; i < destRows; ++i) {
587  memcpy(dest.bitmap + (i * destCols), src.data + ((destRows - i - 1) * src.step1() * sizeof(uint16_t)), static_cast<size_t>(src.step));
588  }
589  }
590  else {
591  for (unsigned int i = 0; i < destRows; ++i) {
592  memcpy(dest.bitmap + (i * destCols), src.data + (i * src.step1() * sizeof(uint16_t)), static_cast<size_t>(src.step));
593  }
594  }
595  }
596  }
597  else {
598  throw(vpException(vpException::fatalError, "cv:Mat format not supported for conversion into vpImage<uint16_t>"));
599  }
600 }
601 
609 void vpImageConvert::convert(const cv::Mat &src, vpImage<vpRGBf> &dest, bool flip)
610 {
611  dest.resize(static_cast<unsigned int>(src.rows), static_cast<unsigned int>(src.cols));
612  unsigned int destRows = dest.getRows();
613  unsigned int destCols = dest.getCols();
614 
615  if (src.type() == CV_32FC3) {
616  vpRGBf rgbVal;
617  for (unsigned int i = 0; i < destRows; ++i)
618  for (unsigned int j = 0; j < destCols; ++j) {
619  cv::Vec3f tmp = src.at<cv::Vec3f>(static_cast<int>(i), static_cast<int>(j));
620  rgbVal.R = tmp[2];
621  rgbVal.G = tmp[1];
622  rgbVal.B = tmp[0];
623  if (flip) {
624  dest[destRows - i - 1][j] = rgbVal;
625  }
626  else {
627  dest[i][j] = rgbVal;
628  }
629  }
630  }
631  else {
632  throw vpException(vpException::badValue, "cv::Mat type is not supported!");
633  }
634 }
635 
672 void vpImageConvert::convert(const vpImage<vpRGBa> &src, cv::Mat &dest)
673 {
674  cv::Mat vpToMat(static_cast<int>(src.getRows()), static_cast<int>(src.getCols()), CV_8UC4, (void *)src.bitmap);
675  cv::cvtColor(vpToMat, dest, cv::COLOR_RGBA2BGR);
676 }
677 
716 void vpImageConvert::convert(const vpImage<unsigned char> &src, cv::Mat &dest, bool copyData)
717 {
718  if (copyData) {
719  cv::Mat tmpMap(static_cast<int>(src.getRows()), static_cast<int>(src.getCols()), CV_8UC1, (void *)src.bitmap);
720  dest = tmpMap.clone();
721  }
722  else {
723  dest = cv::Mat(static_cast<int>(src.getRows()), static_cast<int>(src.getCols()), CV_8UC1, (void *)src.bitmap);
724  }
725 }
726 
727 void vpImageConvert::convert(const vpImage<float> &src, cv::Mat &dest, bool copyData)
728 {
729  if (copyData) {
730  cv::Mat tmpMap(static_cast<int>(src.getRows()), static_cast<int>(src.getCols()), CV_32FC1, (void *)src.bitmap);
731  dest = tmpMap.clone();
732  }
733  else {
734  dest = cv::Mat(static_cast<int>(src.getRows()), static_cast<int>(src.getCols()), CV_32FC1, (void *)src.bitmap);
735  }
736 }
737 
738 void vpImageConvert::convert(const vpImage<double> &src, cv::Mat &dest, bool copyData)
739 {
740  unsigned int nbRows = src.getRows();
741  unsigned int nbCols = src.getCols();
742  vpImage<float> I_float(nbRows, nbCols);
743  for (unsigned int i = 0; i < nbRows; ++i) {
744  for (unsigned int j = 0; j < nbCols; ++j) {
745  I_float[i][j] = static_cast<float>(src[i][j]);
746  }
747  }
748  convert(I_float, dest, copyData);
749 }
750 
751 void vpImageConvert::convert(const vpImage<vpRGBf> &src, cv::Mat &dest)
752 {
753  cv::Mat vpToMat(static_cast<int>(src.getRows()), static_cast<int>(src.getCols()), CV_32FC3, (void *)src.bitmap);
754  cv::cvtColor(vpToMat, dest, cv::COLOR_RGB2BGR);
755 }
756 
757 #endif
758 
759 #ifdef VISP_HAVE_YARP
793 void vpImageConvert::convert(const vpImage<unsigned char> &src, yarp::sig::ImageOf<yarp::sig::PixelMono> *dest,
794  bool copyData)
795 {
796  if (copyData) {
797  dest->resize(src.getWidth(), src.getHeight());
798  memcpy(dest->getRawImage(), src.bitmap, src.getHeight() * src.getWidth());
799  }
800  else {
801  dest->setExternal(src.bitmap, static_cast<int>(src.getCols()), static_cast<int>(src.getRows()));
802  }
803 }
804 
843 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelMono> *src, vpImage<unsigned char> &dest,
844  bool copyData)
845 {
846  dest.resize(src->height(), src->width());
847  if (copyData) {
848  memcpy(dest.bitmap, src->getRawImage(), src->height() * src->width() * sizeof(yarp::sig::PixelMono));
849  }
850  else {
851  dest.bitmap = src->getRawImage();
852  }
853 }
854 
889 void vpImageConvert::convert(const vpImage<vpRGBa> &src, yarp::sig::ImageOf<yarp::sig::PixelRgba> *dest, bool copyData)
890 {
891  if (copyData) {
892  dest->resize(src.getWidth(), src.getHeight());
893  memcpy(dest->getRawImage(), src.bitmap, src.getHeight() * src.getWidth() * sizeof(vpRGBa));
894  }
895  else {
896  dest->setExternal(src.bitmap, static_cast<int>(src.getCols()), static_cast<int>(src.getRows()));
897  }
898 }
899 
938 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelRgba> *src, vpImage<vpRGBa> &dest, bool copyData)
939 {
940  dest.resize(src->height(), src->width());
941  if (copyData)
942  memcpy(dest.bitmap, src->getRawImage(), src->height() * src->width() * sizeof(yarp::sig::PixelRgba));
943  else {
944  dest.bitmap = static_cast<vpRGBa *>(src->getRawImage());
945  }
946 }
947 
980 void vpImageConvert::convert(const vpImage<vpRGBa> &src, yarp::sig::ImageOf<yarp::sig::PixelRgb> *dest)
981 {
982  const unsigned int srcRows = src.getRows(), srcWidth = src.getWidth();
983  dest->resize(src.getWidth(), src.getHeight());
984  for (unsigned int i = 0; i < srcRows; ++i) {
985  for (unsigned int j = 0; j < srcWidth; ++j) {
986  dest->pixel(j, i).r = src[i][j].R;
987  dest->pixel(j, i).g = src[i][j].G;
988  dest->pixel(j, i).b = src[i][j].B;
989  }
990  }
991 }
992 
1031 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelRgb> *src, vpImage<vpRGBa> &dest)
1032 {
1033  const int srcHeight = src->height(), srcWidth = src->width();
1034  dest.resize(srcHeight, srcWidth);
1035  for (int i = 0; i < srcHeight; ++i) {
1036  for (int j = 0; j < srcWidth; ++j) {
1037  dest[i][j].R = src->pixel(j, i).r;
1038  dest[i][j].G = src->pixel(j, i).g;
1039  dest[i][j].B = src->pixel(j, i).b;
1040  dest[i][j].A = vpRGBa::alpha_default;
1041  }
1042  }
1043 }
1044 
1045 #endif
1046 
1047 #define vpSAT(c) \
1048  if (c & (~255)) { \
1049  if (c < 0) \
1050  {c = 0;} \
1051  else \
1052  {c = 255;} \
1053  }
1066 void vpImageConvert::YUYVToRGBa(unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height)
1067 {
1068  unsigned char *s;
1069  unsigned char *d;
1070  int w, h;
1071  int r, g, b, cr, cg, cb, y1, y2;
1072 
1073  h = static_cast<int>(height);
1074  w = static_cast<int>(width);
1075  s = yuyv;
1076  d = rgba;
1077  while (h--) {
1078  int c = w >> 1;
1079  while (c--) {
1080  y1 = *s++;
1081  cb = ((*s - 128) * 454) >> 8;
1082  cg = (*s++ - 128) * 88;
1083  y2 = *s++;
1084  cr = ((*s - 128) * 359) >> 8;
1085  cg = (cg + ((*s++ - 128) * 183)) >> 8;
1086 
1087  r = y1 + cr;
1088  b = y1 + cb;
1089  g = y1 - cg;
1090  vpSAT(r) vpSAT(g) vpSAT(b)
1091 
1092  *d++ = static_cast<unsigned char>(r);
1093  *d++ = static_cast<unsigned char>(g);
1094  *d++ = static_cast<unsigned char>(b);
1095  *d++ = vpRGBa::alpha_default;
1096 
1097  r = y2 + cr;
1098  b = y2 + cb;
1099  g = y2 - cg;
1100  vpSAT(r) vpSAT(g) vpSAT(b)
1101 
1102  *d++ = static_cast<unsigned char>(r);
1103  *d++ = static_cast<unsigned char>(g);
1104  *d++ = static_cast<unsigned char>(b);
1105  *d++ = vpRGBa::alpha_default;
1106  }
1107  }
1108 }
1109 
1120 void vpImageConvert::YUYVToRGB(unsigned char *yuyv, unsigned char *rgb, unsigned int width, unsigned int height)
1121 {
1122  unsigned char *s;
1123  unsigned char *d;
1124  int h, w;
1125  int r, g, b, cr, cg, cb, y1, y2;
1126 
1127  h = static_cast<int>(height);
1128  w = static_cast<int>(width);
1129  s = yuyv;
1130  d = rgb;
1131  while (h--) {
1132  int c = w >> 1;
1133  while (c--) {
1134  y1 = *s++;
1135  cb = ((*s - 128) * 454) >> 8;
1136  cg = (*s++ - 128) * 88;
1137  y2 = *s++;
1138  cr = ((*s - 128) * 359) >> 8;
1139  cg = (cg + ((*s++ - 128) * 183)) >> 8;
1140 
1141  r = y1 + cr;
1142  b = y1 + cb;
1143  g = y1 - cg;
1144  vpSAT(r) vpSAT(g) vpSAT(b)
1145 
1146  *d++ = static_cast<unsigned char>(r);
1147  *d++ = static_cast<unsigned char>(g);
1148  *d++ = static_cast<unsigned char>(b);
1149 
1150  r = y2 + cr;
1151  b = y2 + cb;
1152  g = y2 - cg;
1153  vpSAT(r) vpSAT(g) vpSAT(b)
1154 
1155  *d++ = static_cast<unsigned char>(r);
1156  *d++ = static_cast<unsigned char>(g);
1157  *d++ = static_cast<unsigned char>(b);
1158  }
1159  }
1160 }
1161 
1172 void vpImageConvert::YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
1173 {
1174  unsigned int i = 0, j = 0;
1175  const unsigned int doubleSize = size * 2;
1176  while (j < doubleSize) {
1177  grey[i++] = yuyv[j];
1178  grey[i++] = yuyv[j + 2];
1179  j += 4;
1180  }
1181 }
1182 
1192 void vpImageConvert::YUV411ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
1193 {
1194 #if 1
1195  // std::cout << "call optimized ConvertYUV411ToRGBa()" << std::endl;
1196  for (unsigned int i = size / 4; i; --i) {
1197  int U = static_cast<int>((*yuv++ - 128) * 0.354);
1198  int U5 = 5 * U;
1199  int Y0 = *yuv++;
1200  int Y1 = *yuv++;
1201  int V = static_cast<int>((*yuv++ - 128) * 0.707);
1202  int V2 = 2 * V;
1203  int Y2 = *yuv++;
1204  int Y3 = *yuv++;
1205  int UV = -U - V;
1206 
1207  // Original equations
1208  // R = Y + 1.402 V
1209  // G = Y - 0.344 U - 0.714 V
1210  // B = Y + 1.772 U
1211  int R = Y0 + V2;
1212  if ((R >> 8) > 0) {
1213  R = 255;
1214  }
1215  else if (R < 0) {
1216  R = 0;
1217  }
1218 
1219  int G = Y0 + UV;
1220  if ((G >> 8) > 0) {
1221  G = 255;
1222  }
1223  else if (G < 0) {
1224  G = 0;
1225  }
1226 
1227  int B = Y0 + U5;
1228  if ((B >> 8) > 0) {
1229  B = 255;
1230  }
1231  else if (B < 0) {
1232  B = 0;
1233  }
1234 
1235  *rgba++ = static_cast<unsigned char>(R);
1236  *rgba++ = static_cast<unsigned char>(G);
1237  *rgba++ = static_cast<unsigned char>(B);
1238  *rgba++ = vpRGBa::alpha_default;
1239 
1240  //---
1241  R = Y1 + V2;
1242  if ((R >> 8) > 0) {
1243  R = 255;
1244  }
1245  else if (R < 0) {
1246  R = 0;
1247  }
1248 
1249  G = Y1 + UV;
1250  if ((G >> 8) > 0) {
1251  G = 255;
1252  }
1253  else if (G < 0) {
1254  G = 0;
1255  }
1256 
1257  B = Y1 + U5;
1258  if ((B >> 8) > 0) {
1259  B = 255;
1260  }
1261  else if (B < 0) {
1262  B = 0;
1263  }
1264 
1265  *rgba++ = static_cast<unsigned char>(R);
1266  *rgba++ = static_cast<unsigned char>(G);
1267  *rgba++ = static_cast<unsigned char>(B);
1268  *rgba++ = vpRGBa::alpha_default;
1269 
1270  //---
1271  R = Y2 + V2;
1272  if ((R >> 8) > 0) {
1273  R = 255;
1274  }
1275  else if (R < 0) {
1276  R = 0;
1277  }
1278 
1279  G = Y2 + UV;
1280  if ((G >> 8) > 0) {
1281  G = 255;
1282  }
1283  else if (G < 0) {
1284  G = 0;
1285  }
1286 
1287  B = Y2 + U5;
1288  if ((B >> 8) > 0) {
1289  B = 255;
1290  }
1291  else if (B < 0) {
1292  B = 0;
1293  }
1294 
1295  *rgba++ = static_cast<unsigned char>(R);
1296  *rgba++ = static_cast<unsigned char>(G);
1297  *rgba++ = static_cast<unsigned char>(B);
1298  *rgba++ = vpRGBa::alpha_default;
1299 
1300  //---
1301  R = Y3 + V2;
1302  if ((R >> 8) > 0) {
1303  R = 255;
1304  }
1305  else if (R < 0) {
1306  R = 0;
1307  }
1308 
1309  G = Y3 + UV;
1310  if ((G >> 8) > 0) {
1311  G = 255;
1312  }
1313  else if (G < 0) {
1314  G = 0;
1315  }
1316 
1317  B = Y3 + U5;
1318  if ((B >> 8) > 0) {
1319  B = 255;
1320  }
1321  else if (B < 0) {
1322  B = 0;
1323  }
1324 
1325  *rgba++ = static_cast<unsigned char>(R);
1326  *rgba++ = static_cast<unsigned char>(G);
1327  *rgba++ = static_cast<unsigned char>(B);
1328  *rgba++ = vpRGBa::alpha_default;
1329  }
1330 #else
1331  // tres tres lent ....
1332  unsigned int i = 0, j = 0;
1333  unsigned char r, g, b;
1334  const unsigned int iterLimit = (numpixels * 3) / 2;
1335  while (j < iterLimit) {
1336 
1337  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 3], r, g, b);
1338  rgba[i] = r;
1339  rgba[i + 1] = g;
1340  rgba[i + 2] = b;
1341  rgba[i + 3] = vpRGBa::alpha_default;
1342  i += 4;
1343 
1344  YUVToRGB(yuv[j + 2], yuv[j], yuv[j + 3], r, g, b);
1345  rgba[i] = r;
1346  rgba[i + 1] = g;
1347  rgba[i + 2] = b;
1348  rgba[i + 3] = vpRGBa::alpha_default;
1349  i += 4;
1350 
1351  YUVToRGB(yuv[j + 4], yuv[j], yuv[j + 3], r, g, b);
1352  rgba[i] = r;
1353  rgba[i + 1] = g;
1354  rgba[i + 2] = b;
1355  rgba[i + 3] = vpRGBa::alpha_default;
1356  i += 4;
1357 
1358  YUVToRGB(yuv[j + 5], yuv[j], yuv[j + 3], r, g, b);
1359  rgba[i] = r;
1360  rgba[i + 1] = g;
1361  rgba[i + 2] = b;
1362  rgba[i + 3] = vpRGBa::alpha_default;
1363  i += 4;
1364 
1365  j += 6;
1366  }
1367 #endif
1368 }
1369 
1382 void vpImageConvert::YUV422ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
1383 {
1384 
1385 #if 1
1386  // std::cout << "call optimized convertYUV422ToRGBa()" << std::endl;
1387  for (unsigned int i = size / 2; i; --i) {
1388  int U = static_cast<int>((*yuv++ - 128) * 0.354);
1389  int U5 = 5 * U;
1390  int Y0 = *yuv++;
1391  int V = static_cast<int>((*yuv++ - 128) * 0.707);
1392  int V2 = 2 * V;
1393  int Y1 = *yuv++;
1394  int UV = -U - V;
1395 
1396  //---
1397  int R = Y0 + V2;
1398  if ((R >> 8) > 0) {
1399  R = 255;
1400  }
1401  else if (R < 0) {
1402  R = 0;
1403  }
1404 
1405  int G = Y0 + UV;
1406  if ((G >> 8) > 0) {
1407  G = 255;
1408  }
1409  else if (G < 0) {
1410  G = 0;
1411  }
1412 
1413  int B = Y0 + U5;
1414  if ((B >> 8) > 0) {
1415  B = 255;
1416  }
1417  else if (B < 0) {
1418  B = 0;
1419  }
1420 
1421  *rgba++ = static_cast<unsigned char>(R);
1422  *rgba++ = static_cast<unsigned char>(G);
1423  *rgba++ = static_cast<unsigned char>(B);
1424  *rgba++ = vpRGBa::alpha_default;
1425 
1426  //---
1427  R = Y1 + V2;
1428  if ((R >> 8) > 0) {
1429  R = 255;
1430  }
1431  else if (R < 0) {
1432  R = 0;
1433  }
1434 
1435  G = Y1 + UV;
1436  if ((G >> 8) > 0) {
1437  G = 255;
1438  }
1439  else if (G < 0) {
1440  G = 0;
1441  }
1442 
1443  B = Y1 + U5;
1444  if ((B >> 8) > 0) {
1445  B = 255;
1446  }
1447  else if (B < 0) {
1448  B = 0;
1449  }
1450 
1451  *rgba++ = static_cast<unsigned char>(R);
1452  *rgba++ = static_cast<unsigned char>(G);
1453  *rgba++ = static_cast<unsigned char>(B);
1454  *rgba++ = vpRGBa::alpha_default;
1455  }
1456 
1457 #else
1458  // tres tres lent ....
1459  unsigned int i = 0, j = 0;
1460  unsigned char r, g, b;
1461  const unsigned int doubleSize = size * 2;
1462  while (j < doubleSize) {
1463 
1464  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 2], r, g, b);
1465  rgba[i] = r;
1466  rgba[i + 1] = g;
1467  rgba[i + 2] = b;
1468  rgba[i + 3] = vpRGBa::alpha_default;
1469  i += 4;
1470 
1471  YUVToRGB(yuv[j + 3], yuv[j], yuv[j + 2], r, g, b);
1472  rgba[i] = r;
1473  rgba[i + 1] = g;
1474  rgba[i + 2] = b;
1475  rgba[i + 3] = vpRGBa::alpha_default;
1476  i += 4;
1477  j += 4;
1478  }
1479 #endif
1480 }
1481 
1490 void vpImageConvert::YUV411ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
1491 {
1492  unsigned int i = 0, j = 0;
1493  const unsigned int iterLimit = (size * 3) / 2;
1494  while (j < iterLimit) {
1495  grey[i] = yuv[j + 1];
1496  grey[i + 1] = yuv[j + 2];
1497  grey[i + 2] = yuv[j + 4];
1498  grey[i + 3] = yuv[j + 5];
1499 
1500  i += 4;
1501 
1502  j += 6;
1503  }
1504 }
1505 
1516 void vpImageConvert::YUV422ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
1517 {
1518 #if 1
1519  // std::cout << "call optimized convertYUV422ToRGB()" << std::endl;
1520  for (unsigned int i = size / 2; i; --i) {
1521  int U = static_cast<int>((*yuv++ - 128) * 0.354);
1522  int U5 = 5 * U;
1523  int Y0 = *yuv++;
1524  int V = static_cast<int>((*yuv++ - 128) * 0.707);
1525  int V2 = 2 * V;
1526  int Y1 = *yuv++;
1527  int UV = -U - V;
1528 
1529  //---
1530  int R = Y0 + V2;
1531  if ((R >> 8) > 0) {
1532  R = 255;
1533  }
1534  else if (R < 0) {
1535  R = 0;
1536  }
1537 
1538  int G = Y0 + UV;
1539  if ((G >> 8) > 0) {
1540  G = 255;
1541  }
1542  else if (G < 0) {
1543  G = 0;
1544  }
1545 
1546  int B = Y0 + U5;
1547  if ((B >> 8) > 0) {
1548  B = 255;
1549  }
1550  else if (B < 0) {
1551  B = 0;
1552  }
1553 
1554  *rgb++ = static_cast<unsigned char>(R);
1555  *rgb++ = static_cast<unsigned char>(G);
1556  *rgb++ = static_cast<unsigned char>(B);
1557 
1558  //---
1559  R = Y1 + V2;
1560  if ((R >> 8) > 0) {
1561  R = 255;
1562  }
1563  else if (R < 0) {
1564  R = 0;
1565  }
1566 
1567  G = Y1 + UV;
1568  if ((G >> 8) > 0) {
1569  G = 255;
1570  }
1571  else if (G < 0) {
1572  G = 0;
1573  }
1574 
1575  B = Y1 + U5;
1576  if ((B >> 8) > 0) {
1577  B = 255;
1578  }
1579  else if (B < 0) {
1580  B = 0;
1581  }
1582 
1583  *rgb++ = static_cast<unsigned char>(R);
1584  *rgb++ = static_cast<unsigned char>(G);
1585  *rgb++ = static_cast<unsigned char>(B);
1586  }
1587 
1588 #else
1589  // tres tres lent ....
1590  unsigned int i = 0, j = 0;
1591  unsigned char r, g, b;
1592  const unsigned int doubleSize = size * 2;
1593  while (j < doubleSize) {
1594 
1595  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 2], r, g, b);
1596  rgb[i] = r;
1597  rgb[i + 1] = g;
1598  rgb[i + 2] = b;
1599  i += 3;
1600 
1601  YUVToRGB(yuv[j + 3], yuv[j], yuv[j + 2], r, g, b);
1602  rgb[i] = r;
1603  rgb[i + 1] = g;
1604  rgb[i + 2] = b;
1605  i += 3;
1606  j += 4;
1607  }
1608 #endif
1609 }
1610 
1621 void vpImageConvert::YUV422ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
1622 {
1623  unsigned int i = 0, j = 0;
1624  const unsigned int doubleSize = size * 2;
1625 
1626  while (j < doubleSize) {
1627  grey[i++] = yuv[j + 1];
1628  grey[i++] = yuv[j + 3];
1629  j += 4;
1630  }
1631 }
1632 
1641 void vpImageConvert::YUV411ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
1642 {
1643 #if 1
1644  // std::cout << "call optimized ConvertYUV411ToRGB()" << std::endl;
1645  for (unsigned int i = size / 4; i; --i) {
1646  int U = static_cast<int>((*yuv++ - 128) * 0.354);
1647  int U5 = 5 * U;
1648  int Y0 = *yuv++;
1649  int Y1 = *yuv++;
1650  int V = static_cast<int>((*yuv++ - 128) * 0.707);
1651  int V2 = 2 * V;
1652  int Y2 = *yuv++;
1653  int Y3 = *yuv++;
1654  int UV = -U - V;
1655 
1656  // Original equations
1657  // R = Y + 1.402 V
1658  // G = Y - 0.344 U - 0.714 V
1659  // B = Y + 1.772 U
1660  int R = Y0 + V2;
1661  if ((R >> 8) > 0) {
1662  R = 255;
1663  }
1664  else if (R < 0) {
1665  R = 0;
1666  }
1667 
1668  int G = Y0 + UV;
1669  if ((G >> 8) > 0) {
1670  G = 255;
1671  }
1672  else if (G < 0) {
1673  G = 0;
1674  }
1675 
1676  int B = Y0 + U5;
1677  if ((B >> 8) > 0) {
1678  B = 255;
1679  }
1680  else if (B < 0) {
1681  B = 0;
1682  }
1683 
1684  *rgb++ = static_cast<unsigned char>(R);
1685  *rgb++ = static_cast<unsigned char>(G);
1686  *rgb++ = static_cast<unsigned char>(B);
1687 
1688  //---
1689  R = Y1 + V2;
1690  if ((R >> 8) > 0) {
1691  R = 255;
1692  }
1693  else if (R < 0) {
1694  R = 0;
1695  }
1696 
1697  G = Y1 + UV;
1698  if ((G >> 8) > 0) {
1699  G = 255;
1700  }
1701  else if (G < 0) {
1702  G = 0;
1703  }
1704 
1705  B = Y1 + U5;
1706  if ((B >> 8) > 0) {
1707  B = 255;
1708  }
1709  else if (B < 0) {
1710  B = 0;
1711  }
1712 
1713  *rgb++ = static_cast<unsigned char>(R);
1714  *rgb++ = static_cast<unsigned char>(G);
1715  *rgb++ = static_cast<unsigned char>(B);
1716 
1717  //---
1718  R = Y2 + V2;
1719  if ((R >> 8) > 0) {
1720  R = 255;
1721  }
1722  else if (R < 0) {
1723  R = 0;
1724  }
1725 
1726  G = Y2 + UV;
1727  if ((G >> 8) > 0) {
1728  G = 255;
1729  }
1730  else if (G < 0) {
1731  G = 0;
1732  }
1733 
1734  B = Y2 + U5;
1735  if ((B >> 8) > 0) {
1736  B = 255;
1737  }
1738  else if (B < 0) {
1739  B = 0;
1740  }
1741 
1742  *rgb++ = static_cast<unsigned char>(R);
1743  *rgb++ = static_cast<unsigned char>(G);
1744  *rgb++ = static_cast<unsigned char>(B);
1745 
1746  //---
1747  R = Y3 + V2;
1748  if ((R >> 8) > 0) {
1749  R = 255;
1750  }
1751  else if (R < 0) {
1752  R = 0;
1753  }
1754 
1755  G = Y3 + UV;
1756  if ((G >> 8) > 0) {
1757  G = 255;
1758  }
1759  else if (G < 0) {
1760  G = 0;
1761  }
1762 
1763  B = Y3 + U5;
1764  if ((B >> 8) > 0) {
1765  B = 255;
1766  }
1767  else if (B < 0) {
1768  B = 0;
1769  }
1770 
1771  *rgb++ = static_cast<unsigned char>(R);
1772  *rgb++ = static_cast<unsigned char>(G);
1773  *rgb++ = static_cast<unsigned char>(B);
1774  }
1775 #else
1776  // tres tres lent ....
1777 
1778  unsigned int i = 0, j = 0;
1779  unsigned char r, g, b;
1780 
1781  const unsigned int iterLimit = (size * 3) / 2;
1782  while (j < iterLimit) {
1783  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 3], r, g, b);
1784  rgb[i] = r;
1785  rgb[i + 1] = g;
1786  rgb[i + 2] = b;
1787  i += 3;
1788 
1789  YUVToRGB(yuv[j + 2], yuv[j], yuv[j + 3], r, g, b);
1790  rgb[i] = r;
1791  rgb[i + 1] = g;
1792  rgb[i + 2] = b;
1793  i += 3;
1794 
1795  YUVToRGB(yuv[j + 4], yuv[j], yuv[j + 3], r, g, b);
1796  rgb[i] = r;
1797  rgb[i + 1] = g;
1798  rgb[i + 2] = b;
1799  i += 3;
1800 
1801  YUVToRGB(yuv[j + 5], yuv[j], yuv[j + 3], r, g, b);
1802  rgb[i] = r;
1803  rgb[i + 1] = g;
1804  rgb[i + 2] = b;
1805  i += 3;
1806  // TRACE("r= %d g=%d b=%d", r, g, b);
1807 
1808  j += 6;
1809  }
1810 #endif
1811 }
1812 
1823 void vpImageConvert::YUV420ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
1824 {
1825  // std::cout << "call optimized ConvertYUV420ToRGBa()" << std::endl;
1826  int U, V, R, G, B, V2, U5, UV;
1827  int Y0, Y1, Y2, Y3;
1828  unsigned int size = width * height;
1829  unsigned char *iU = yuv + size;
1830  unsigned char *iV = yuv + ((5 * size) / 4);
1831  const unsigned int halfHeight = height / 2, halfWidth = width / 2;
1832  for (unsigned int i = 0; i < halfHeight; ++i) {
1833  for (unsigned int j = 0; j < halfWidth; ++j) {
1834  U = static_cast<int>((*iU++ - 128) * 0.354);
1835  U5 = 5 * U;
1836  V = static_cast<int>((*iV++ - 128) * 0.707);
1837  V2 = 2 * V;
1838  UV = -U - V;
1839  Y0 = *yuv++;
1840  Y1 = *yuv;
1841  yuv = yuv + (width - 1);
1842  Y2 = *yuv++;
1843  Y3 = *yuv;
1844  yuv = (yuv - width) + 1;
1845 
1846  // Original equations
1847  // R = Y + 1.402 V
1848  // G = Y - 0.344 U - 0.714 V
1849  // B = Y + 1.772 U
1850  R = Y0 + V2;
1851  if ((R >> 8) > 0) {
1852  R = 255;
1853  }
1854  else if (R < 0) {
1855  R = 0;
1856  }
1857 
1858  G = Y0 + UV;
1859  if ((G >> 8) > 0) {
1860  G = 255;
1861  }
1862  else if (G < 0) {
1863  G = 0;
1864  }
1865 
1866  B = Y0 + U5;
1867  if ((B >> 8) > 0) {
1868  B = 255;
1869  }
1870  else if (B < 0) {
1871  B = 0;
1872  }
1873 
1874  *rgba++ = static_cast<unsigned char>(R);
1875  *rgba++ = static_cast<unsigned char>(G);
1876  *rgba++ = static_cast<unsigned char>(B);
1877  *rgba++ = vpRGBa::alpha_default;
1878 
1879  //---
1880  R = Y1 + V2;
1881  if ((R >> 8) > 0) {
1882  R = 255;
1883  }
1884  else if (R < 0) {
1885  R = 0;
1886  }
1887 
1888  G = Y1 + UV;
1889  if ((G >> 8) > 0) {
1890  G = 255;
1891  }
1892  else if (G < 0) {
1893  G = 0;
1894  }
1895 
1896  B = Y1 + U5;
1897  if ((B >> 8) > 0) {
1898  B = 255;
1899  }
1900  else if (B < 0) {
1901  B = 0;
1902  }
1903 
1904  *rgba++ = static_cast<unsigned char>(R);
1905  *rgba++ = static_cast<unsigned char>(G);
1906  *rgba++ = static_cast<unsigned char>(B);
1907  *rgba = vpRGBa::alpha_default;
1908  rgba = rgba + 4 * width - 7;
1909 
1910  //---
1911  R = Y2 + V2;
1912  if ((R >> 8) > 0) {
1913  R = 255;
1914  }
1915  else if (R < 0) {
1916  R = 0;
1917  }
1918 
1919  G = Y2 + UV;
1920  if ((G >> 8) > 0) {
1921  G = 255;
1922  }
1923  else if (G < 0) {
1924  G = 0;
1925  }
1926 
1927  B = Y2 + U5;
1928  if ((B >> 8) > 0) {
1929  B = 255;
1930  }
1931  else if (B < 0) {
1932  B = 0;
1933  }
1934 
1935  *rgba++ = static_cast<unsigned char>(R);
1936  *rgba++ = static_cast<unsigned char>(G);
1937  *rgba++ = static_cast<unsigned char>(B);
1938  *rgba++ = vpRGBa::alpha_default;
1939 
1940  //---
1941  R = Y3 + V2;
1942  if ((R >> 8) > 0) {
1943  R = 255;
1944  }
1945  else if (R < 0) {
1946  R = 0;
1947  }
1948 
1949  G = Y3 + UV;
1950  if ((G >> 8) > 0) {
1951  G = 255;
1952  }
1953  else if (G < 0) {
1954  G = 0;
1955  }
1956 
1957  B = Y3 + U5;
1958  if ((B >> 8) > 0) {
1959  B = 255;
1960  }
1961  else if (B < 0) {
1962  B = 0;
1963  }
1964 
1965  *rgba++ = static_cast<unsigned char>(R);
1966  *rgba++ = static_cast<unsigned char>(G);
1967  *rgba++ = static_cast<unsigned char>(B);
1968  *rgba = vpRGBa::alpha_default;
1969  rgba = (rgba - (4 * width)) + 1;
1970  }
1971  yuv += width;
1972  rgba += 4 * width;
1973  }
1974 }
1975 
1984 void vpImageConvert::YUV420ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
1985 {
1986  // std::cout << "call optimized ConvertYUV420ToRGB()" << std::endl;
1987  int U, V, R, G, B, V2, U5, UV;
1988  int Y0, Y1, Y2, Y3;
1989  unsigned int size = width * height;
1990  unsigned char *iU = yuv + size;
1991  unsigned char *iV = yuv + ((5 * size) / 4);
1992  const unsigned int halfHeight = height / 2, halfWidth = width / 2;
1993  for (unsigned int i = 0; i < halfHeight; ++i) {
1994  for (unsigned int j = 0; j < halfWidth; ++j) {
1995  U = static_cast<int>((*iU++ - 128) * 0.354);
1996  U5 = 5 * U;
1997  V = static_cast<int>((*iV++ - 128) * 0.707);
1998  V2 = 2 * V;
1999  UV = -U - V;
2000  Y0 = *yuv++;
2001  Y1 = *yuv;
2002  yuv = yuv + (width - 1);
2003  Y2 = *yuv++;
2004  Y3 = *yuv;
2005  yuv = (yuv - width) + 1;
2006 
2007  // Original equations
2008  // R = Y + 1.402 V
2009  // G = Y - 0.344 U - 0.714 V
2010  // B = Y + 1.772 U
2011  R = Y0 + V2;
2012  if ((R >> 8) > 0) {
2013  R = 255;
2014  }
2015  else if (R < 0) {
2016  R = 0;
2017  }
2018 
2019  G = Y0 + UV;
2020  if ((G >> 8) > 0) {
2021  G = 255;
2022  }
2023  else if (G < 0) {
2024  G = 0;
2025  }
2026 
2027  B = Y0 + U5;
2028  if ((B >> 8) > 0) {
2029  B = 255;
2030  }
2031  else if (B < 0) {
2032  B = 0;
2033  }
2034 
2035  *rgb++ = static_cast<unsigned char>(R);
2036  *rgb++ = static_cast<unsigned char>(G);
2037  *rgb++ = static_cast<unsigned char>(B);
2038 
2039  //---
2040  R = Y1 + V2;
2041  if ((R >> 8) > 0) {
2042  R = 255;
2043  }
2044  else if (R < 0) {
2045  R = 0;
2046  }
2047 
2048  G = Y1 + UV;
2049  if ((G >> 8) > 0) {
2050  G = 255;
2051  }
2052  else if (G < 0) {
2053  G = 0;
2054  }
2055 
2056  B = Y1 + U5;
2057  if ((B >> 8) > 0) {
2058  B = 255;
2059  }
2060  else if (B < 0) {
2061  B = 0;
2062  }
2063 
2064  *rgb++ = static_cast<unsigned char>(R);
2065  *rgb++ = static_cast<unsigned char>(G);
2066  *rgb = static_cast<unsigned char>(B);
2067  rgb = rgb + ((3 * width) - 5);
2068 
2069  //---
2070  R = Y2 + V2;
2071  if ((R >> 8) > 0) {
2072  R = 255;
2073  }
2074  else if (R < 0) {
2075  R = 0;
2076  }
2077 
2078  G = Y2 + UV;
2079  if ((G >> 8) > 0) {
2080  G = 255;
2081  }
2082  else if (G < 0) {
2083  G = 0;
2084  }
2085 
2086  B = Y2 + U5;
2087  if ((B >> 8) > 0) {
2088  B = 255;
2089  }
2090  else if (B < 0) {
2091  B = 0;
2092  }
2093 
2094  *rgb++ = static_cast<unsigned char>(R);
2095  *rgb++ = static_cast<unsigned char>(G);
2096  *rgb++ = static_cast<unsigned char>(B);
2097 
2098  //---
2099  R = Y3 + V2;
2100  if ((R >> 8) > 0) {
2101  R = 255;
2102  }
2103  else if (R < 0) {
2104  R = 0;
2105  }
2106 
2107  G = Y3 + UV;
2108  if ((G >> 8) > 0) {
2109  G = 255;
2110  }
2111  else if (G < 0) {
2112  G = 0;
2113  }
2114 
2115  B = Y3 + U5;
2116  if ((B >> 8) > 0) {
2117  B = 255;
2118  }
2119  else if (B < 0) {
2120  B = 0;
2121  }
2122 
2123  *rgb++ = static_cast<unsigned char>(R);
2124  *rgb++ = static_cast<unsigned char>(G);
2125  *rgb = static_cast<unsigned char>(B);
2126  rgb = (rgb - (3 * width)) + 1;
2127  }
2128  yuv += width;
2129  rgb += 3 * width;
2130  }
2131 }
2132 
2140 void vpImageConvert::YUV420ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
2141 {
2142  for (unsigned int i = 0; i < size; ++i) {
2143  *grey++ = *yuv++;
2144  }
2145 }
2146 
2156 void vpImageConvert::YUV444ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
2157 {
2158  for (unsigned int i = 0; i < size; ++i) {
2159  int U = static_cast<int>((*yuv++ - 128) * 0.354);
2160  int U5 = 5 * U;
2161  int Y = *yuv++;
2162  int V = static_cast<int>((*yuv++ - 128) * 0.707);
2163  int V2 = 2 * V;
2164  int UV = -U - V;
2165 
2166  // Original equations
2167  // R = Y + 1.402 V
2168  // G = Y - 0.344 U - 0.714 V
2169  // B = Y + 1.772 U
2170  int R = Y + V2;
2171  if ((R >> 8) > 0) {
2172  R = 255;
2173  }
2174  else if (R < 0) {
2175  R = 0;
2176  }
2177 
2178  int G = Y + UV;
2179  if ((G >> 8) > 0) {
2180  G = 255;
2181  }
2182  else if (G < 0) {
2183  G = 0;
2184  }
2185 
2186  int B = Y + U5;
2187  if ((B >> 8) > 0) {
2188  B = 255;
2189  }
2190  else if (B < 0) {
2191  B = 0;
2192  }
2193 
2194  *rgba++ = static_cast<unsigned char>(R);
2195  *rgba++ = static_cast<unsigned char>(G);
2196  *rgba++ = static_cast<unsigned char>(B);
2197  *rgba++ = vpRGBa::alpha_default;
2198  }
2199 }
2200 
2208 void vpImageConvert::YUV444ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
2209 {
2210  for (unsigned int i = 0; i < size; ++i) {
2211  int U = static_cast<int>((*yuv++ - 128) * 0.354);
2212  int U5 = 5 * U;
2213  int Y = *yuv++;
2214  int V = static_cast<int>((*yuv++ - 128) * 0.707);
2215  int V2 = 2 * V;
2216  int UV = -U - V;
2217 
2218  // Original equations
2219  // R = Y + 1.402 V
2220  // G = Y - 0.344 U - 0.714 V
2221  // B = Y + 1.772 U
2222  int R = Y + V2;
2223  if ((R >> 8) > 0) {
2224  R = 255;
2225  }
2226  else if (R < 0) {
2227  R = 0;
2228  }
2229 
2230  int G = Y + UV;
2231  if ((G >> 8) > 0) {
2232  G = 255;
2233  }
2234  else if (G < 0) {
2235  G = 0;
2236  }
2237 
2238  int B = Y + U5;
2239  if ((B >> 8) > 0) {
2240  B = 255;
2241  }
2242  else if (B < 0) {
2243  B = 0;
2244  }
2245 
2246  *rgb++ = static_cast<unsigned char>(R);
2247  *rgb++ = static_cast<unsigned char>(G);
2248  *rgb++ = static_cast<unsigned char>(B);
2249  }
2250 }
2251 
2259 void vpImageConvert::YUV444ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
2260 {
2261  ++yuv;
2262  for (unsigned int i = 0; i < size; ++i) {
2263  *grey++ = *yuv;
2264  yuv = yuv + 3;
2265  }
2266 }
2267 
2278 void vpImageConvert::YV12ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
2279 {
2280  // std::cout << "call optimized ConvertYV12ToRGBa()" << std::endl;
2281  int U, V, R, G, B, V2, U5, UV;
2282  int Y0, Y1, Y2, Y3;
2283  unsigned int size = width * height;
2284  unsigned char *iV = yuv + size;
2285  unsigned char *iU = yuv + ((5 * size) / 4);
2286  const unsigned int halfHeight = height / 2, halfWidth = width / 2;
2287  for (unsigned int i = 0; i < halfHeight; ++i) {
2288  for (unsigned int j = 0; j < halfWidth; ++j) {
2289  U = static_cast<int>((*iU++ - 128) * 0.354);
2290  U5 = 5 * U;
2291  V = static_cast<int>((*iV++ - 128) * 0.707);
2292  V2 = 2 * V;
2293  UV = -U - V;
2294  Y0 = *yuv++;
2295  Y1 = *yuv;
2296  yuv = yuv + (width - 1);
2297  Y2 = *yuv++;
2298  Y3 = *yuv;
2299  yuv = (yuv - width) + 1;
2300 
2301  // Original equations
2302  // R = Y + 1.402 V
2303  // G = Y - 0.344 U - 0.714 V
2304  // B = Y + 1.772 U
2305  R = Y0 + V2;
2306  if ((R >> 8) > 0) {
2307  R = 255;
2308  }
2309  else if (R < 0) {
2310  R = 0;
2311  }
2312 
2313  G = Y0 + UV;
2314  if ((G >> 8) > 0) {
2315  G = 255;
2316  }
2317  else if (G < 0) {
2318  G = 0;
2319  }
2320 
2321  B = Y0 + U5;
2322  if ((B >> 8) > 0) {
2323  B = 255;
2324  }
2325  else if (B < 0) {
2326  B = 0;
2327  }
2328 
2329  *rgba++ = static_cast<unsigned char>(R);
2330  *rgba++ = static_cast<unsigned char>(G);
2331  *rgba++ = static_cast<unsigned char>(B);
2332  *rgba++ = vpRGBa::alpha_default;
2333 
2334  //---
2335  R = Y1 + V2;
2336  if ((R >> 8) > 0) {
2337  R = 255;
2338  }
2339  else if (R < 0) {
2340  R = 0;
2341  }
2342 
2343  G = Y1 + UV;
2344  if ((G >> 8) > 0) {
2345  G = 255;
2346  }
2347  else if (G < 0) {
2348  G = 0;
2349  }
2350 
2351  B = Y1 + U5;
2352  if ((B >> 8) > 0) {
2353  B = 255;
2354  }
2355  else if (B < 0) {
2356  B = 0;
2357  }
2358 
2359  *rgba++ = static_cast<unsigned char>(R);
2360  *rgba++ = static_cast<unsigned char>(G);
2361  *rgba++ = static_cast<unsigned char>(B);
2362  *rgba = 0;
2363  rgba = rgba + ((4 * width) - 7);
2364 
2365  //---
2366  R = Y2 + V2;
2367  if ((R >> 8) > 0) {
2368  R = 255;
2369  }
2370  else if (R < 0) {
2371  R = 0;
2372  }
2373 
2374  G = Y2 + UV;
2375  if ((G >> 8) > 0) {
2376  G = 255;
2377  }
2378  else if (G < 0) {
2379  G = 0;
2380  }
2381 
2382  B = Y2 + U5;
2383  if ((B >> 8) > 0) {
2384  B = 255;
2385  }
2386  else if (B < 0) {
2387  B = 0;
2388  }
2389 
2390  *rgba++ = static_cast<unsigned char>(R);
2391  *rgba++ = static_cast<unsigned char>(G);
2392  *rgba++ = static_cast<unsigned char>(B);
2393  *rgba++ = vpRGBa::alpha_default;
2394 
2395  //---
2396  R = Y3 + V2;
2397  if ((R >> 8) > 0) {
2398  R = 255;
2399  }
2400  else if (R < 0) {
2401  R = 0;
2402  }
2403 
2404  G = Y3 + UV;
2405  if ((G >> 8) > 0) {
2406  G = 255;
2407  }
2408  else if (G < 0) {
2409  G = 0;
2410  }
2411 
2412  B = Y3 + U5;
2413  if ((B >> 8) > 0) {
2414  B = 255;
2415  }
2416  else if (B < 0) {
2417  B = 0;
2418  }
2419 
2420  *rgba++ = static_cast<unsigned char>(R);
2421  *rgba++ = static_cast<unsigned char>(G);
2422  *rgba++ = static_cast<unsigned char>(B);
2423  *rgba = vpRGBa::alpha_default;
2424  rgba = (rgba - (4 * width)) + 1;
2425  }
2426  yuv += width;
2427  rgba += 4 * width;
2428  }
2429 }
2430 
2439 void vpImageConvert::YV12ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int height, unsigned int width)
2440 {
2441  // std::cout << "call optimized ConvertYV12ToRGB()" << std::endl;
2442  int U, V, R, G, B, V2, U5, UV;
2443  int Y0, Y1, Y2, Y3;
2444  unsigned int size = width * height;
2445  unsigned char *iV = yuv + size;
2446  unsigned char *iU = yuv + ((5 * size) / 4);
2447  const unsigned int halfHeight = height / 2, halfWidth = width / 2;
2448  for (unsigned int i = 0; i < halfHeight; ++i) {
2449  for (unsigned int j = 0; j < halfWidth; ++j) {
2450  U = static_cast<int>((*iU++ - 128) * 0.354);
2451  U5 = 5 * U;
2452  V = static_cast<int>((*iV++ - 128) * 0.707);
2453  V2 = 2 * V;
2454  UV = -U - V;
2455  Y0 = *yuv++;
2456  Y1 = *yuv;
2457  yuv = yuv + (width - 1);
2458  Y2 = *yuv++;
2459  Y3 = *yuv;
2460  yuv = (yuv - width) + 1;
2461 
2462  // Original equations
2463  // R = Y + 1.402 V
2464  // G = Y - 0.344 U - 0.714 V
2465  // B = Y + 1.772 U
2466  R = Y0 + V2;
2467  if ((R >> 8) > 0) {
2468  R = 255;
2469  }
2470  else if (R < 0) {
2471  R = 0;
2472  }
2473 
2474  G = Y0 + UV;
2475  if ((G >> 8) > 0) {
2476  G = 255;
2477  }
2478  else if (G < 0) {
2479  G = 0;
2480  }
2481 
2482  B = Y0 + U5;
2483  if ((B >> 8) > 0) {
2484  B = 255;
2485  }
2486  else if (B < 0) {
2487  B = 0;
2488  }
2489 
2490  *rgb++ = static_cast<unsigned char>(R);
2491  *rgb++ = static_cast<unsigned char>(G);
2492  *rgb++ = static_cast<unsigned char>(B);
2493 
2494  //---
2495  R = Y1 + V2;
2496  if ((R >> 8) > 0) {
2497  R = 255;
2498  }
2499  else if (R < 0) {
2500  R = 0;
2501  }
2502 
2503  G = Y1 + UV;
2504  if ((G >> 8) > 0) {
2505  G = 255;
2506  }
2507  else if (G < 0) {
2508  G = 0;
2509  }
2510 
2511  B = Y1 + U5;
2512  if ((B >> 8) > 0) {
2513  B = 255;
2514  }
2515  else if (B < 0) {
2516  B = 0;
2517  }
2518 
2519  *rgb++ = static_cast<unsigned char>(R);
2520  *rgb++ = static_cast<unsigned char>(G);
2521  *rgb = static_cast<unsigned char>(B);
2522  rgb = rgb + ((3 * width) - 5);
2523 
2524  //---
2525  R = Y2 + V2;
2526  if ((R >> 8) > 0) {
2527  R = 255;
2528  }
2529  else if (R < 0) {
2530  R = 0;
2531  }
2532 
2533  G = Y2 + UV;
2534  if ((G >> 8) > 0) {
2535  G = 255;
2536  }
2537  else if (G < 0) {
2538  G = 0;
2539  }
2540 
2541  B = Y2 + U5;
2542  if ((B >> 8) > 0) {
2543  B = 255;
2544  }
2545  else if (B < 0) {
2546  B = 0;
2547  }
2548 
2549  *rgb++ = static_cast<unsigned char>(R);
2550  *rgb++ = static_cast<unsigned char>(G);
2551  *rgb++ = static_cast<unsigned char>(B);
2552 
2553  //---
2554  R = Y3 + V2;
2555  if ((R >> 8) > 0) {
2556  R = 255;
2557  }
2558  else if (R < 0) {
2559  R = 0;
2560  }
2561 
2562  G = Y3 + UV;
2563  if ((G >> 8) > 0) {
2564  G = 255;
2565  }
2566  else if (G < 0) {
2567  G = 0;
2568  }
2569 
2570  B = Y3 + U5;
2571  if ((B >> 8) > 0) {
2572  B = 255;
2573  }
2574  else if (B < 0) {
2575  B = 0;
2576  }
2577 
2578  *rgb++ = static_cast<unsigned char>(R);
2579  *rgb++ = static_cast<unsigned char>(G);
2580  *rgb = static_cast<unsigned char>(B);
2581  rgb = (rgb - (3 * width)) + 1;
2582  }
2583  yuv += width;
2584  rgb += 3 * width;
2585  }
2586 }
2587 
2598 void vpImageConvert::YVU9ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
2599 {
2600  // std::cout << "call optimized ConvertYVU9ToRGBa()" << std::endl;
2601  int U, V, R, G, B, V2, U5, UV;
2602  int Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9, Y10, Y11, Y12, Y13, Y14, Y15;
2603  unsigned int size = width * height;
2604  unsigned char *iV = yuv + size;
2605  unsigned char *iU = yuv + ((17 * size) / 16);
2606  const unsigned int quarterHeight = height / 4, quarterWidth = width / 4;
2607  for (unsigned int i = 0; i < quarterHeight; ++i) {
2608  for (unsigned int j = 0; j < quarterWidth; ++j) {
2609  U = static_cast<int>((*iU++ - 128) * 0.354);
2610  U5 = 5 * U;
2611  V = static_cast<int>((*iV++ - 128) * 0.707);
2612  V2 = 2 * V;
2613  UV = -U - V;
2614  Y0 = *yuv++;
2615  Y1 = *yuv++;
2616  Y2 = *yuv++;
2617  Y3 = *yuv;
2618  yuv = yuv + (width - 3);
2619  Y4 = *yuv++;
2620  Y5 = *yuv++;
2621  Y6 = *yuv++;
2622  Y7 = *yuv;
2623  yuv = yuv + (width - 3);
2624  Y8 = *yuv++;
2625  Y9 = *yuv++;
2626  Y10 = *yuv++;
2627  Y11 = *yuv;
2628  yuv = yuv + (width - 3);
2629  Y12 = *yuv++;
2630  Y13 = *yuv++;
2631  Y14 = *yuv++;
2632  Y15 = *yuv;
2633  yuv = (yuv - (3 * width)) + 1;
2634 
2635  // Original equations
2636  // R = Y + 1.402 V
2637  // G = Y - 0.344 U - 0.714 V
2638  // B = Y + 1.772 U
2639  R = Y0 + V2;
2640  if ((R >> 8) > 0) {
2641  R = 255;
2642  }
2643  else if (R < 0) {
2644  R = 0;
2645  }
2646 
2647  G = Y0 + UV;
2648  if ((G >> 8) > 0) {
2649  G = 255;
2650  }
2651  else if (G < 0) {
2652  G = 0;
2653  }
2654 
2655  B = Y0 + U5;
2656  if ((B >> 8) > 0) {
2657  B = 255;
2658  }
2659  else if (B < 0) {
2660  B = 0;
2661  }
2662 
2663  *rgba++ = static_cast<unsigned char>(R);
2664  *rgba++ = static_cast<unsigned char>(G);
2665  *rgba++ = static_cast<unsigned char>(B);
2666  *rgba++ = vpRGBa::alpha_default;
2667 
2668  //---
2669  R = Y1 + V2;
2670  if ((R >> 8) > 0) {
2671  R = 255;
2672  }
2673  else if (R < 0) {
2674  R = 0;
2675  }
2676 
2677  G = Y1 + UV;
2678  if ((G >> 8) > 0) {
2679  G = 255;
2680  }
2681  else if (G < 0) {
2682  G = 0;
2683  }
2684 
2685  B = Y1 + U5;
2686  if ((B >> 8) > 0) {
2687  B = 255;
2688  }
2689  else if (B < 0) {
2690  B = 0;
2691  }
2692 
2693  *rgba++ = static_cast<unsigned char>(R);
2694  *rgba++ = static_cast<unsigned char>(G);
2695  *rgba++ = static_cast<unsigned char>(B);
2696  *rgba++ = vpRGBa::alpha_default;
2697 
2698  //---
2699  R = Y2 + V2;
2700  if ((R >> 8) > 0) {
2701  R = 255;
2702  }
2703  else if (R < 0) {
2704  R = 0;
2705  }
2706 
2707  G = Y2 + UV;
2708  if ((G >> 8) > 0) {
2709  G = 255;
2710  }
2711  else if (G < 0) {
2712  G = 0;
2713  }
2714 
2715  B = Y2 + U5;
2716  if ((B >> 8) > 0) {
2717  B = 255;
2718  }
2719  else if (B < 0) {
2720  B = 0;
2721  }
2722 
2723  *rgba++ = static_cast<unsigned char>(R);
2724  *rgba++ = static_cast<unsigned char>(G);
2725  *rgba++ = static_cast<unsigned char>(B);
2726  *rgba++ = vpRGBa::alpha_default;
2727 
2728  //---
2729  R = Y3 + V2;
2730  if ((R >> 8) > 0) {
2731  R = 255;
2732  }
2733  else if (R < 0) {
2734  R = 0;
2735  }
2736 
2737  G = Y3 + UV;
2738  if ((G >> 8) > 0) {
2739  G = 255;
2740  }
2741  else if (G < 0) {
2742  G = 0;
2743  }
2744 
2745  B = Y3 + U5;
2746  if ((B >> 8) > 0) {
2747  B = 255;
2748  }
2749  else if (B < 0) {
2750  B = 0;
2751  }
2752 
2753  *rgba++ = static_cast<unsigned char>(R);
2754  *rgba++ = static_cast<unsigned char>(G);
2755  *rgba++ = static_cast<unsigned char>(B);
2756  *rgba = vpRGBa::alpha_default;
2757  rgba = rgba + ((4 * width) - 15);
2758 
2759  R = Y4 + V2;
2760  if ((R >> 8) > 0) {
2761  R = 255;
2762  }
2763  else if (R < 0) {
2764  R = 0;
2765  }
2766 
2767  G = Y4 + UV;
2768  if ((G >> 8) > 0) {
2769  G = 255;
2770  }
2771  else if (G < 0) {
2772  G = 0;
2773  }
2774 
2775  B = Y4 + U5;
2776  if ((B >> 8) > 0) {
2777  B = 255;
2778  }
2779  else if (B < 0) {
2780  B = 0;
2781  }
2782 
2783  *rgba++ = static_cast<unsigned char>(R);
2784  *rgba++ = static_cast<unsigned char>(G);
2785  *rgba++ = static_cast<unsigned char>(B);
2786  *rgba++ = vpRGBa::alpha_default;
2787 
2788  //---
2789  R = Y5 + V2;
2790  if ((R >> 8) > 0) {
2791  R = 255;
2792  }
2793  else if (R < 0) {
2794  R = 0;
2795  }
2796 
2797  G = Y5 + UV;
2798  if ((G >> 8) > 0) {
2799  G = 255;
2800  }
2801  else if (G < 0) {
2802  G = 0;
2803  }
2804 
2805  B = Y5 + U5;
2806  if ((B >> 8) > 0) {
2807  B = 255;
2808  }
2809  else if (B < 0) {
2810  B = 0;
2811  }
2812 
2813  *rgba++ = static_cast<unsigned char>(R);
2814  *rgba++ = static_cast<unsigned char>(G);
2815  *rgba++ = static_cast<unsigned char>(B);
2816  *rgba++ = vpRGBa::alpha_default;
2817 
2818  //---
2819  R = Y6 + V2;
2820  if ((R >> 8) > 0) {
2821  R = 255;
2822  }
2823  else if (R < 0) {
2824  R = 0;
2825  }
2826 
2827  G = Y6 + UV;
2828  if ((G >> 8) > 0) {
2829  G = 255;
2830  }
2831  else if (G < 0) {
2832  G = 0;
2833  }
2834 
2835  B = Y6 + U5;
2836  if ((B >> 8) > 0) {
2837  B = 255;
2838  }
2839  else if (B < 0) {
2840  B = 0;
2841  }
2842 
2843  *rgba++ = static_cast<unsigned char>(R);
2844  *rgba++ = static_cast<unsigned char>(G);
2845  *rgba++ = static_cast<unsigned char>(B);
2846  *rgba++ = vpRGBa::alpha_default;
2847 
2848  //---
2849  R = Y7 + V2;
2850  if ((R >> 8) > 0) {
2851  R = 255;
2852  }
2853  else if (R < 0) {
2854  R = 0;
2855  }
2856 
2857  G = Y7 + UV;
2858  if ((G >> 8) > 0) {
2859  G = 255;
2860  }
2861  else if (G < 0) {
2862  G = 0;
2863  }
2864 
2865  B = Y7 + U5;
2866  if ((B >> 8) > 0) {
2867  B = 255;
2868  }
2869  else if (B < 0) {
2870  B = 0;
2871  }
2872 
2873  *rgba++ = static_cast<unsigned char>(R);
2874  *rgba++ = static_cast<unsigned char>(G);
2875  *rgba++ = static_cast<unsigned char>(B);
2876  *rgba = vpRGBa::alpha_default;
2877  rgba = rgba + ((4 * width) - 15);
2878 
2879  R = Y8 + V2;
2880  if ((R >> 8) > 0) {
2881  R = 255;
2882  }
2883  else if (R < 0) {
2884  R = 0;
2885  }
2886 
2887  G = Y8 + UV;
2888  if ((G >> 8) > 0) {
2889  G = 255;
2890  }
2891  else if (G < 0) {
2892  G = 0;
2893  }
2894 
2895  B = Y8 + U5;
2896  if ((B >> 8) > 0) {
2897  B = 255;
2898  }
2899  else if (B < 0) {
2900  B = 0;
2901  }
2902 
2903  *rgba++ = static_cast<unsigned char>(R);
2904  *rgba++ = static_cast<unsigned char>(G);
2905  *rgba++ = static_cast<unsigned char>(B);
2906  *rgba++ = vpRGBa::alpha_default;
2907 
2908  //---
2909  R = Y9 + V2;
2910  if ((R >> 8) > 0) {
2911  R = 255;
2912  }
2913  else if (R < 0) {
2914  R = 0;
2915  }
2916 
2917  G = Y9 + UV;
2918  if ((G >> 8) > 0) {
2919  G = 255;
2920  }
2921  else if (G < 0) {
2922  G = 0;
2923  }
2924 
2925  B = Y9 + U5;
2926  if ((B >> 8) > 0) {
2927  B = 255;
2928  }
2929  else if (B < 0) {
2930  B = 0;
2931  }
2932 
2933  *rgba++ = static_cast<unsigned char>(R);
2934  *rgba++ = static_cast<unsigned char>(G);
2935  *rgba++ = static_cast<unsigned char>(B);
2936  *rgba++ = vpRGBa::alpha_default;
2937 
2938  //---
2939  R = Y10 + V2;
2940  if ((R >> 8) > 0) {
2941  R = 255;
2942  }
2943  else if (R < 0) {
2944  R = 0;
2945  }
2946 
2947  G = Y10 + UV;
2948  if ((G >> 8) > 0) {
2949  G = 255;
2950  }
2951  else if (G < 0) {
2952  G = 0;
2953  }
2954 
2955  B = Y10 + U5;
2956  if ((B >> 8) > 0) {
2957  B = 255;
2958  }
2959  else if (B < 0) {
2960  B = 0;
2961  }
2962 
2963  *rgba++ = static_cast<unsigned char>(R);
2964  *rgba++ = static_cast<unsigned char>(G);
2965  *rgba++ = static_cast<unsigned char>(B);
2966  *rgba++ = vpRGBa::alpha_default;
2967 
2968  //---
2969  R = Y11 + V2;
2970  if ((R >> 8) > 0) {
2971  R = 255;
2972  }
2973  else if (R < 0) {
2974  R = 0;
2975  }
2976 
2977  G = Y11 + UV;
2978  if ((G >> 8) > 0) {
2979  G = 255;
2980  }
2981  else if (G < 0) {
2982  G = 0;
2983  }
2984 
2985  B = Y11 + U5;
2986  if ((B >> 8) > 0) {
2987  B = 255;
2988  }
2989  else if (B < 0) {
2990  B = 0;
2991  }
2992 
2993  *rgba++ = static_cast<unsigned char>(R);
2994  *rgba++ = static_cast<unsigned char>(G);
2995  *rgba++ = static_cast<unsigned char>(B);
2996  *rgba = vpRGBa::alpha_default;
2997  rgba = rgba + ((4 * width) - 15);
2998 
2999  R = Y12 + V2;
3000  if ((R >> 8) > 0) {
3001  R = 255;
3002  }
3003  else if (R < 0) {
3004  R = 0;
3005  }
3006 
3007  G = Y12 + UV;
3008  if ((G >> 8) > 0) {
3009  G = 255;
3010  }
3011  else if (G < 0) {
3012  G = 0;
3013  }
3014 
3015  B = Y12 + U5;
3016  if ((B >> 8) > 0) {
3017  B = 255;
3018  }
3019  else if (B < 0) {
3020  B = 0;
3021  }
3022 
3023  *rgba++ = static_cast<unsigned char>(R);
3024  *rgba++ = static_cast<unsigned char>(G);
3025  *rgba++ = static_cast<unsigned char>(B);
3026  *rgba++ = vpRGBa::alpha_default;
3027 
3028  //---
3029  R = Y13 + V2;
3030  if ((R >> 8) > 0) {
3031  R = 255;
3032  }
3033  else if (R < 0) {
3034  R = 0;
3035  }
3036 
3037  G = Y13 + UV;
3038  if ((G >> 8) > 0) {
3039  G = 255;
3040  }
3041  else if (G < 0) {
3042  G = 0;
3043  }
3044 
3045  B = Y13 + U5;
3046  if ((B >> 8) > 0) {
3047  B = 255;
3048  }
3049  else if (B < 0) {
3050  B = 0;
3051  }
3052 
3053  *rgba++ = static_cast<unsigned char>(R);
3054  *rgba++ = static_cast<unsigned char>(G);
3055  *rgba++ = static_cast<unsigned char>(B);
3056  *rgba++ = vpRGBa::alpha_default;
3057 
3058  //---
3059  R = Y14 + V2;
3060  if ((R >> 8) > 0) {
3061  R = 255;
3062  }
3063  else if (R < 0) {
3064  R = 0;
3065  }
3066 
3067  G = Y14 + UV;
3068  if ((G >> 8) > 0) {
3069  G = 255;
3070  }
3071  else if (G < 0) {
3072  G = 0;
3073  }
3074 
3075  B = Y14 + U5;
3076  if ((B >> 8) > 0) {
3077  B = 255;
3078  }
3079  else if (B < 0) {
3080  B = 0;
3081  }
3082 
3083  *rgba++ = static_cast<unsigned char>(R);
3084  *rgba++ = static_cast<unsigned char>(G);
3085  *rgba++ = static_cast<unsigned char>(B);
3086  *rgba++ = vpRGBa::alpha_default;
3087 
3088  //---
3089  R = Y15 + V2;
3090  if ((R >> 8) > 0) {
3091  R = 255;
3092  }
3093  else if (R < 0) {
3094  R = 0;
3095  }
3096 
3097  G = Y15 + UV;
3098  if ((G >> 8) > 0) {
3099  G = 255;
3100  }
3101  else if (G < 0) {
3102  G = 0;
3103  }
3104 
3105  B = Y15 + U5;
3106  if ((B >> 8) > 0) {
3107  B = 255;
3108  }
3109  else if (B < 0) {
3110  B = 0;
3111  }
3112 
3113  *rgba++ = static_cast<unsigned char>(R);
3114  *rgba++ = static_cast<unsigned char>(G);
3115  *rgba++ = static_cast<unsigned char>(B);
3116  *rgba = vpRGBa::alpha_default;
3117  rgba = (rgba - (12 * width)) + 1;
3118  }
3119  yuv += 3 * width;
3120  rgba += 12 * width;
3121  }
3122 }
3123 
3131 void vpImageConvert::YVU9ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int height, unsigned int width)
3132 {
3133  // std::cout << "call optimized ConvertYVU9ToRGB()" << std::endl;
3134  int U, V, R, G, B, V2, U5, UV;
3135  int Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9, Y10, Y11, Y12, Y13, Y14, Y15;
3136  unsigned int size = width * height;
3137  unsigned char *iV = yuv + size;
3138  unsigned char *iU = yuv + ((17 * size) / 16);
3139  const unsigned int quarterHeight = height / 4, quarterWidth = width / 4;
3140  for (unsigned int i = 0; i < quarterHeight; ++i) {
3141  for (unsigned int j = 0; j < quarterWidth; ++j) {
3142  U = static_cast<int>((*iU++ - 128) * 0.354);
3143  U5 = 5 * U;
3144  V = static_cast<int>((*iV++ - 128) * 0.707);
3145  V2 = 2 * V;
3146  UV = -U - V;
3147  Y0 = *yuv++;
3148  Y1 = *yuv++;
3149  Y2 = *yuv++;
3150  Y3 = *yuv;
3151  yuv = yuv + (width - 3);
3152  Y4 = *yuv++;
3153  Y5 = *yuv++;
3154  Y6 = *yuv++;
3155  Y7 = *yuv;
3156  yuv = yuv + (width - 3);
3157  Y8 = *yuv++;
3158  Y9 = *yuv++;
3159  Y10 = *yuv++;
3160  Y11 = *yuv;
3161  yuv = yuv + (width - 3);
3162  Y12 = *yuv++;
3163  Y13 = *yuv++;
3164  Y14 = *yuv++;
3165  Y15 = *yuv;
3166  yuv = (yuv - (3 * width)) + 1;
3167 
3168  // Original equations
3169  // R = Y + 1.402 V
3170  // G = Y - 0.344 U - 0.714 V
3171  // B = Y + 1.772 U
3172  R = Y0 + V2;
3173  if ((R >> 8) > 0) {
3174  R = 255;
3175  }
3176  else if (R < 0) {
3177  R = 0;
3178  }
3179 
3180  G = Y0 + UV;
3181  if ((G >> 8) > 0) {
3182  G = 255;
3183  }
3184  else if (G < 0) {
3185  G = 0;
3186  }
3187 
3188  B = Y0 + U5;
3189  if ((B >> 8) > 0) {
3190  B = 255;
3191  }
3192  else if (B < 0) {
3193  B = 0;
3194  }
3195 
3196  *rgb++ = static_cast<unsigned char>(R);
3197  *rgb++ = static_cast<unsigned char>(G);
3198  *rgb++ = static_cast<unsigned char>(B);
3199 
3200  //---
3201  R = Y1 + V2;
3202  if ((R >> 8) > 0) {
3203  R = 255;
3204  }
3205  else if (R < 0) {
3206  R = 0;
3207  }
3208 
3209  G = Y1 + UV;
3210  if ((G >> 8) > 0) {
3211  G = 255;
3212  }
3213  else if (G < 0) {
3214  G = 0;
3215  }
3216 
3217  B = Y1 + U5;
3218  if ((B >> 8) > 0) {
3219  B = 255;
3220  }
3221  else if (B < 0) {
3222  B = 0;
3223  }
3224 
3225  *rgb++ = static_cast<unsigned char>(R);
3226  *rgb++ = static_cast<unsigned char>(G);
3227  *rgb++ = static_cast<unsigned char>(B);
3228 
3229  //---
3230  R = Y2 + V2;
3231  if ((R >> 8) > 0) {
3232  R = 255;
3233  }
3234  else if (R < 0) {
3235  R = 0;
3236  }
3237 
3238  G = Y2 + UV;
3239  if ((G >> 8) > 0) {
3240  G = 255;
3241  }
3242  else if (G < 0) {
3243  G = 0;
3244  }
3245 
3246  B = Y2 + U5;
3247  if ((B >> 8) > 0) {
3248  B = 255;
3249  }
3250  else if (B < 0) {
3251  B = 0;
3252  }
3253 
3254  *rgb++ = static_cast<unsigned char>(R);
3255  *rgb++ = static_cast<unsigned char>(G);
3256  *rgb++ = static_cast<unsigned char>(B);
3257 
3258  //---
3259  R = Y3 + V2;
3260  if ((R >> 8) > 0) {
3261  R = 255;
3262  }
3263  else if (R < 0) {
3264  R = 0;
3265  }
3266 
3267  G = Y3 + UV;
3268  if ((G >> 8) > 0) {
3269  G = 255;
3270  }
3271  else if (G < 0) {
3272  G = 0;
3273  }
3274 
3275  B = Y3 + U5;
3276  if ((B >> 8) > 0) {
3277  B = 255;
3278  }
3279  else if (B < 0) {
3280  B = 0;
3281  }
3282 
3283  *rgb++ = static_cast<unsigned char>(R);
3284  *rgb++ = static_cast<unsigned char>(G);
3285  *rgb = static_cast<unsigned char>(B);
3286  rgb = rgb + ((3 * width) - 11);
3287 
3288  R = Y4 + V2;
3289  if ((R >> 8) > 0) {
3290  R = 255;
3291  }
3292  else if (R < 0) {
3293  R = 0;
3294  }
3295 
3296  G = Y4 + UV;
3297  if ((G >> 8) > 0) {
3298  G = 255;
3299  }
3300  else if (G < 0) {
3301  G = 0;
3302  }
3303 
3304  B = Y4 + U5;
3305  if ((B >> 8) > 0) {
3306  B = 255;
3307  }
3308  else if (B < 0) {
3309  B = 0;
3310  }
3311 
3312  *rgb++ = static_cast<unsigned char>(R);
3313  *rgb++ = static_cast<unsigned char>(G);
3314  *rgb++ = static_cast<unsigned char>(B);
3315 
3316  //---
3317  R = Y5 + V2;
3318  if ((R >> 8) > 0) {
3319  R = 255;
3320  }
3321  else if (R < 0) {
3322  R = 0;
3323  }
3324 
3325  G = Y5 + UV;
3326  if ((G >> 8) > 0) {
3327  G = 255;
3328  }
3329  else if (G < 0) {
3330  G = 0;
3331  }
3332 
3333  B = Y5 + U5;
3334  if ((B >> 8) > 0) {
3335  B = 255;
3336  }
3337  else if (B < 0) {
3338  B = 0;
3339  }
3340 
3341  *rgb++ = static_cast<unsigned char>(R);
3342  *rgb++ = static_cast<unsigned char>(G);
3343  *rgb++ = static_cast<unsigned char>(B);
3344 
3345  //---
3346  R = Y6 + V2;
3347  if ((R >> 8) > 0) {
3348  R = 255;
3349  }
3350  else if (R < 0) {
3351  R = 0;
3352  }
3353 
3354  G = Y6 + UV;
3355  if ((G >> 8) > 0) {
3356  G = 255;
3357  }
3358  else if (G < 0) {
3359  G = 0;
3360  }
3361 
3362  B = Y6 + U5;
3363  if ((B >> 8) > 0) {
3364  B = 255;
3365  }
3366  else if (B < 0) {
3367  B = 0;
3368  }
3369 
3370  *rgb++ = static_cast<unsigned char>(R);
3371  *rgb++ = static_cast<unsigned char>(G);
3372  *rgb++ = static_cast<unsigned char>(B);
3373 
3374  //---
3375  R = Y7 + V2;
3376  if ((R >> 8) > 0) {
3377  R = 255;
3378  }
3379  else if (R < 0) {
3380  R = 0;
3381  }
3382 
3383  G = Y7 + UV;
3384  if ((G >> 8) > 0) {
3385  G = 255;
3386  }
3387  else if (G < 0) {
3388  G = 0;
3389  }
3390 
3391  B = Y7 + U5;
3392  if ((B >> 8) > 0) {
3393  B = 255;
3394  }
3395  else if (B < 0) {
3396  B = 0;
3397  }
3398 
3399  *rgb++ = static_cast<unsigned char>(R);
3400  *rgb++ = static_cast<unsigned char>(G);
3401  *rgb = static_cast<unsigned char>(B);
3402  rgb = rgb + ((3 * width) - 11);
3403 
3404  R = Y8 + V2;
3405  if ((R >> 8) > 0) {
3406  R = 255;
3407  }
3408  else if (R < 0) {
3409  R = 0;
3410  }
3411 
3412  G = Y8 + UV;
3413  if ((G >> 8) > 0) {
3414  G = 255;
3415  }
3416  else if (G < 0) {
3417  G = 0;
3418  }
3419 
3420  B = Y8 + U5;
3421  if ((B >> 8) > 0) {
3422  B = 255;
3423  }
3424  else if (B < 0) {
3425  B = 0;
3426  }
3427 
3428  *rgb++ = static_cast<unsigned char>(R);
3429  *rgb++ = static_cast<unsigned char>(G);
3430  *rgb++ = static_cast<unsigned char>(B);
3431 
3432  //---
3433  R = Y9 + V2;
3434  if ((R >> 8) > 0) {
3435  R = 255;
3436  }
3437  else if (R < 0) {
3438  R = 0;
3439  }
3440 
3441  G = Y9 + UV;
3442  if ((G >> 8) > 0) {
3443  G = 255;
3444  }
3445  else if (G < 0) {
3446  G = 0;
3447  }
3448 
3449  B = Y9 + U5;
3450  if ((B >> 8) > 0) {
3451  B = 255;
3452  }
3453  else if (B < 0) {
3454  B = 0;
3455  }
3456 
3457  *rgb++ = static_cast<unsigned char>(R);
3458  *rgb++ = static_cast<unsigned char>(G);
3459  *rgb++ = static_cast<unsigned char>(B);
3460 
3461  //---
3462  R = Y10 + V2;
3463  if ((R >> 8) > 0) {
3464  R = 255;
3465  }
3466  else if (R < 0) {
3467  R = 0;
3468  }
3469 
3470  G = Y10 + UV;
3471  if ((G >> 8) > 0) {
3472  G = 255;
3473  }
3474  else if (G < 0) {
3475  G = 0;
3476  }
3477 
3478  B = Y10 + U5;
3479  if ((B >> 8) > 0) {
3480  B = 255;
3481  }
3482  else if (B < 0) {
3483  B = 0;
3484  }
3485 
3486  *rgb++ = static_cast<unsigned char>(R);
3487  *rgb++ = static_cast<unsigned char>(G);
3488  *rgb++ = static_cast<unsigned char>(B);
3489 
3490  //---
3491  R = Y11 + V2;
3492  if ((R >> 8) > 0) {
3493  R = 255;
3494  }
3495  else if (R < 0) {
3496  R = 0;
3497  }
3498 
3499  G = Y11 + UV;
3500  if ((G >> 8) > 0) {
3501  G = 255;
3502  }
3503  else if (G < 0) {
3504  G = 0;
3505  }
3506 
3507  B = Y11 + U5;
3508  if ((B >> 8) > 0) {
3509  B = 255;
3510  }
3511  else if (B < 0) {
3512  B = 0;
3513  }
3514 
3515  *rgb++ = static_cast<unsigned char>(R);
3516  *rgb++ = static_cast<unsigned char>(G);
3517  *rgb = static_cast<unsigned char>(B);
3518  rgb = rgb + 3 * width - 11;
3519 
3520  R = Y12 + V2;
3521  if ((R >> 8) > 0) {
3522  R = 255;
3523  }
3524  else if (R < 0) {
3525  R = 0;
3526  }
3527 
3528  G = Y12 + UV;
3529  if ((G >> 8) > 0) {
3530  G = 255;
3531  }
3532  else if (G < 0) {
3533  G = 0;
3534  }
3535 
3536  B = Y12 + U5;
3537  if ((B >> 8) > 0) {
3538  B = 255;
3539  }
3540  else if (B < 0) {
3541  B = 0;
3542  }
3543 
3544  *rgb++ = static_cast<unsigned char>(R);
3545  *rgb++ = static_cast<unsigned char>(G);
3546  *rgb++ = static_cast<unsigned char>(B);
3547 
3548  //---
3549  R = Y13 + V2;
3550  if ((R >> 8) > 0) {
3551  R = 255;
3552  }
3553  else if (R < 0) {
3554  R = 0;
3555  }
3556 
3557  G = Y13 + UV;
3558  if ((G >> 8) > 0) {
3559  G = 255;
3560  }
3561  else if (G < 0) {
3562  G = 0;
3563  }
3564 
3565  B = Y13 + U5;
3566  if ((B >> 8) > 0) {
3567  B = 255;
3568  }
3569  else if (B < 0) {
3570  B = 0;
3571  }
3572 
3573  *rgb++ = static_cast<unsigned char>(R);
3574  *rgb++ = static_cast<unsigned char>(G);
3575  *rgb++ = static_cast<unsigned char>(B);
3576 
3577  //---
3578  R = Y14 + V2;
3579  if ((R >> 8) > 0) {
3580  R = 255;
3581  }
3582  else if (R < 0) {
3583  R = 0;
3584  }
3585 
3586  G = Y14 + UV;
3587  if ((G >> 8) > 0) {
3588  G = 255;
3589  }
3590  else if (G < 0) {
3591  G = 0;
3592  }
3593 
3594  B = Y14 + U5;
3595  if ((B >> 8) > 0) {
3596  B = 255;
3597  }
3598  else if (B < 0) {
3599  B = 0;
3600  }
3601 
3602  *rgb++ = static_cast<unsigned char>(R);
3603  *rgb++ = static_cast<unsigned char>(G);
3604  *rgb++ = static_cast<unsigned char>(B);
3605 
3606  //---
3607  R = Y15 + V2;
3608  if ((R >> 8) > 0) {
3609  R = 255;
3610  }
3611  else if (R < 0) {
3612  R = 0;
3613  }
3614 
3615  G = Y15 + UV;
3616  if ((G >> 8) > 0) {
3617  G = 255;
3618  }
3619  else if (G < 0) {
3620  G = 0;
3621  }
3622 
3623  B = Y15 + U5;
3624  if ((B >> 8) > 0) {
3625  B = 255;
3626  }
3627  else if (B < 0) {
3628  B = 0;
3629  }
3630 
3631  *rgb++ = static_cast<unsigned char>(R);
3632  *rgb++ = static_cast<unsigned char>(G);
3633  *rgb++ = static_cast<unsigned char>(B);
3634  rgb = (rgb - (9 * width)) + 1;
3635  }
3636  yuv += 3 * width;
3637  rgb += 9 * width;
3638  }
3639 }
3640 
3650 void vpImageConvert::RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
3651 {
3652  RGBToRGBa(rgb, rgba, size, 1, false);
3653 }
3654 
3670 void vpImageConvert::RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int width, unsigned int height,
3671  bool flip)
3672 {
3673 #if defined(VISP_HAVE_SIMDLIB)
3674  if (!flip) {
3675  SimdBgrToBgra(rgb, width, height, width * 3, rgba, width * 4, vpRGBa::alpha_default);
3676  }
3677  else {
3678 #endif
3679  // if we have to flip the image, we start from the end last scanline so the
3680  // step is negative
3681  int lineStep = flip ? -static_cast<int>(width * 3) : static_cast<int>(width * 3);
3682 
3683  // starting source address = last line if we need to flip the image
3684  unsigned char *src = flip ? (rgb + (width * height * 3) + lineStep) : rgb;
3685 
3686  unsigned int j = 0;
3687  unsigned int i = 0;
3688 
3689  for (i = 0; i < height; ++i) {
3690  unsigned char *line = src;
3691  for (j = 0; j < width; ++j) {
3692  *rgba++ = *(line++);
3693  *rgba++ = *(line++);
3694  *rgba++ = *(line++);
3695  *rgba++ = vpRGBa::alpha_default;
3696  }
3697  // go to the next line
3698  src += lineStep;
3699  }
3700 #if defined(VISP_HAVE_SIMDLIB)
3701  }
3702 #endif
3703 }
3704 
3717 void vpImageConvert::RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
3718 {
3719 #if defined(VISP_HAVE_SIMDLIB)
3720  SimdBgraToBgr(rgba, size, 1, size * 4, rgb, size * 3);
3721 #else
3722  unsigned char *pt_input = rgba;
3723  unsigned char *pt_end = rgba + (4 * size);
3724  unsigned char *pt_output = rgb;
3725 
3726  while (pt_input != pt_end) {
3727  *(pt_output++) = *(pt_input++); // R
3728  *(pt_output++) = *(pt_input++); // G
3729  *(pt_output++) = *(pt_input++); // B
3730  pt_input++;
3731  }
3732 #endif
3733 }
3734 
3747 void vpImageConvert::RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int size)
3748 {
3749  RGBToGrey(rgb, grey, size, 1, false);
3750 }
3751 
3765 void vpImageConvert::RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height,
3766  bool flip)
3767 {
3768 #if defined(VISP_HAVE_SIMDLIB)
3769  if (!flip) {
3770  SimdRgbToGray(rgb, width, height, width * 3, grey, width);
3771  }
3772  else {
3773 #endif
3774  // if we have to flip the image, we start from the end last scanline so
3775  // the step is negative
3776  int lineStep = flip ? -static_cast<int>(width * 3) : static_cast<int>(width * 3);
3777 
3778  // starting source address = last line if we need to flip the image
3779  unsigned char *src = flip ? (rgb + (width * height * 3) + lineStep) : rgb;
3780 
3781  unsigned int j = 0;
3782  unsigned int i = 0;
3783 
3784  unsigned r, g, b;
3785 
3786  for (i = 0; i < height; ++i) {
3787  unsigned char *line = src;
3788  for (j = 0; j < width; ++j) {
3789  r = *(line++);
3790  g = *(line++);
3791  b = *(line++);
3792  *grey++ = static_cast<unsigned char>((0.2126 * r) + (0.7152 * g) + (0.0722 * b));
3793  }
3794 
3795  // go to the next line
3796  src += lineStep;
3797  }
3798 #if defined(VISP_HAVE_SIMDLIB)
3799  }
3800 #endif
3801 }
3802 
3818 void vpImageConvert::RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int width, unsigned int height,
3819  unsigned int
3820 #if defined(_OPENMP)
3821  nThreads
3822 #endif
3823 )
3824 {
3825 #if defined(VISP_HAVE_SIMDLIB)
3826  const int heightAsInt = static_cast<int>(height);
3827 #if defined(_OPENMP)
3828  if (nThreads > 0) {
3829  omp_set_num_threads(static_cast<int>(nThreads));
3830  }
3831 #pragma omp parallel for
3832 #endif
3833  for (int i = 0; i < heightAsInt; ++i) {
3834  SimdRgbaToGray(rgba + (i * width * 4), width, 1, width * 4, grey + (i * width), width);
3835  }
3836 #else
3837 #if defined(_OPENMP)
3838  (void)nThreads;
3839 #endif
3840  vpImageConvert::RGBaToGrey(rgba, grey, width * height);
3841 #endif
3842 }
3843 
3858 void vpImageConvert::RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int size)
3859 {
3860 #if defined(VISP_HAVE_SIMDLIB)
3861  SimdRgbaToGray(rgba, size, 1, size * 4, grey, size);
3862 #else
3863  unsigned char *pt_input = rgba;
3864  unsigned char *pt_end = rgba + (size * 4);
3865  unsigned char *pt_output = grey;
3866 
3867  while (pt_input != pt_end) {
3868  *pt_output = static_cast<unsigned char>((0.2126 * (*pt_input)) + (0.7152 * (*(pt_input + 1))) + (0.0722 * (*(pt_input + 2))));
3869  pt_input += 4;
3870  pt_output++;
3871  }
3872 #endif
3873 }
3874 
3886 void vpImageConvert::GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int width, unsigned int height)
3887 {
3888 #if defined(VISP_HAVE_SIMDLIB)
3889  SimdGrayToBgra(grey, width, height, width, rgba, width * sizeof(vpRGBa), vpRGBa::alpha_default);
3890 #else
3891  vpImageConvert::GreyToRGBa(grey, rgba, width * height);
3892 #endif
3893 }
3894 
3907 void vpImageConvert::GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int size)
3908 {
3909 #if defined(VISP_HAVE_SIMDLIB)
3910  GreyToRGBa(grey, rgba, size, 1);
3911 #else
3912  unsigned char *pt_input = grey;
3913  unsigned char *pt_end = grey + size;
3914  unsigned char *pt_output = rgba;
3915 
3916  while (pt_input != pt_end) {
3917  unsigned char p = *pt_input;
3918  *(pt_output) = p; // R
3919  *(pt_output + 1) = p; // G
3920  *(pt_output + 2) = p; // B
3921  *(pt_output + 3) = vpRGBa::alpha_default; // A
3922 
3923  pt_input++;
3924  pt_output += 4;
3925  }
3926 #endif
3927 }
3928 
3939 void vpImageConvert::GreyToRGB(unsigned char *grey, unsigned char *rgb, unsigned int size)
3940 {
3941 #if defined(VISP_HAVE_SIMDLIB)
3942  SimdGrayToBgr(grey, size, 1, size, rgb, size * 3);
3943 #else
3944  unsigned char *pt_input = grey;
3945  unsigned char *pt_end = grey + size;
3946  unsigned char *pt_output = rgb;
3947 
3948  while (pt_input != pt_end) {
3949  unsigned char p = *pt_input;
3950  *(pt_output) = p; // R
3951  *(pt_output + 1) = p; // G
3952  *(pt_output + 2) = p; // B
3953 
3954  pt_input++;
3955  pt_output += 3;
3956  }
3957 #endif
3958 }
3959 
3975 void vpImageConvert::BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height,
3976  bool flip)
3977 {
3978 #if defined(VISP_HAVE_SIMDLIB)
3979  if (!flip) {
3980  SimdRgbToBgra(bgr, width, height, width * 3, rgba, width * sizeof(vpRGBa), vpRGBa::alpha_default);
3981  }
3982  else {
3983 #endif
3984  // if we have to flip the image, we start from the end last scanline so the
3985  // step is negative
3986  int lineStep = flip ? -static_cast<int>(width * 3) : static_cast<int>(width * 3);
3987 
3988  // starting source address = last line if we need to flip the image
3989  unsigned char *src = flip ? (bgr + (width * height * 3) + lineStep) : bgr;
3990 
3991  for (unsigned int i = 0; i < height; ++i) {
3992  unsigned char *line = src;
3993  for (unsigned int j = 0; j < width; ++j) {
3994  *rgba++ = *(line + 2);
3995  *rgba++ = *(line + 1);
3996  *rgba++ = *(line + 0);
3997  *rgba++ = vpRGBa::alpha_default;
3998 
3999  line += 3;
4000  }
4001  // go to the next line
4002  src += lineStep;
4003  }
4004 #if defined(VISP_HAVE_SIMDLIB)
4005  }
4006 #endif
4007 }
4008 
4023 void vpImageConvert::BGRaToRGBa(unsigned char *bgra, unsigned char *rgba, unsigned int width, unsigned int height,
4024  bool flip)
4025 {
4026 #if defined(VISP_HAVE_SIMDLIB)
4027  if (!flip) {
4028  SimdBgraToRgba(bgra, width, height, width * 4, rgba, width * 4);
4029  }
4030  else {
4031 #endif
4032  // if we have to flip the image, we start from the end last scanline so the
4033  // step is negative
4034  int lineStep = flip ? -static_cast<int>(width * 4) : static_cast<int>(width * 4);
4035 
4036  // starting source address = last line if we need to flip the image
4037  unsigned char *src = flip ? (bgra + (width * height * 4) + lineStep) : bgra;
4038 
4039  for (unsigned int i = 0; i < height; ++i) {
4040  unsigned char *line = src;
4041  for (unsigned int j = 0; j < width; ++j) {
4042  *rgba++ = *(line + 2);
4043  *rgba++ = *(line + 1);
4044  *rgba++ = *(line + 0);
4045  *rgba++ = *(line + 3);
4046 
4047  line += 4;
4048  }
4049  // go to the next line
4050  src += lineStep;
4051  }
4052 #if defined(VISP_HAVE_SIMDLIB)
4053  }
4054 #endif
4055 }
4056 
4071 void vpImageConvert::BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height,
4072  bool flip,
4073  unsigned int
4074 #if defined(_OPENMP)
4075  nThreads
4076 #endif
4077 )
4078 {
4079 #if defined(VISP_HAVE_SIMDLIB)
4080  const int heightAsInt = static_cast<int>(height);
4081  if (!flip) {
4082 #if defined(_OPENMP)
4083  if (nThreads > 0) {
4084  omp_set_num_threads(static_cast<int>(nThreads));
4085  }
4086 #pragma omp parallel for
4087 #endif
4088  for (int i = 0; i < heightAsInt; ++i) {
4089  SimdBgrToGray(bgr + (i * width * 3), width, 1, width * 3, grey + (i * width), width);
4090  }
4091  }
4092  else {
4093 #endif
4094  // if we have to flip the image, we start from the end last scanline so
4095  // the step is negative
4096  int lineStep = flip ? -static_cast<int>(width * 3) : static_cast<int>(width * 3);
4097 
4098  // starting source address = last line if we need to flip the image
4099  unsigned char *src = flip ? (bgr + (width * height * 3) + lineStep) : bgr;
4100 
4101  for (unsigned int i = 0; i < height; ++i) {
4102  unsigned char *line = src;
4103  for (unsigned int j = 0; j < width; ++j) {
4104  *grey++ = static_cast<unsigned int>((0.2126 * *(line + 2)) + (0.7152 * *(line + 1)) + (0.0722 * *(line + 0)));
4105  line += 3;
4106  }
4107 
4108  // go to the next line
4109  src += lineStep;
4110  }
4111 #if defined(VISP_HAVE_SIMDLIB)
4112  }
4113 #endif
4114 #if !defined(VISP_HAVE_SIMDLIB) && defined(_OPENMP)
4115  (void)nThreads;
4116 #endif
4117 }
4118 
4133 void vpImageConvert::BGRaToGrey(unsigned char *bgra, unsigned char *grey, unsigned int width, unsigned int height,
4134  bool flip,
4135  unsigned int
4136 #if defined(_OPENMP)
4137  nThreads
4138 #endif
4139 )
4140 {
4141 #if defined(VISP_HAVE_SIMDLIB)
4142  if (!flip) {
4143  const int heightAsInt = static_cast<int>(height);
4144 #if defined(_OPENMP)
4145  if (nThreads > 0) {
4146  omp_set_num_threads(static_cast<int>(nThreads));
4147  }
4148 #pragma omp parallel for
4149 #endif
4150  for (int i = 0; i < heightAsInt; ++i) {
4151  SimdBgraToGray(bgra + (i * width * 4), width, 1, width * 4, grey + (i * width), width);
4152  }
4153  }
4154  else {
4155 #endif
4156  // if we have to flip the image, we start from the end last scanline so
4157  // the step is negative
4158  int lineStep = flip ? -static_cast<int>(width * 4) : static_cast<int>(width * 4);
4159 
4160  // starting source address = last line if we need to flip the image
4161  unsigned char *src = flip ? (bgra + (width * height * 4) + lineStep) : bgra;
4162 
4163  for (unsigned int i = 0; i < height; ++i) {
4164  unsigned char *line = src;
4165  for (unsigned int j = 0; j < width; ++j) {
4166  *grey++ = static_cast<unsigned char>((0.2126 * *(line + 2)) + (0.7152 * *(line + 1)) + (0.0722 * *(line + 0)));
4167  line += 4;
4168  }
4169 
4170  // go to the next line
4171  src += lineStep;
4172  }
4173 #if defined(VISP_HAVE_SIMDLIB)
4174  }
4175 #endif
4176 #if !defined(VISP_HAVE_SIMDLIB) && defined(_OPENMP)
4177  (void)nThreads;
4178 #endif
4179 }
4180 
4184 void vpImageConvert::computeYCbCrLUT()
4185 {
4186  if (YCbCrLUTcomputed == false) {
4187  int index = 256;
4188 
4189  while (index--) {
4190 
4191  int aux = index - 128;
4192  vpImageConvert::vpCrr[index] = static_cast<int>(364.6610 * aux) >> 8;
4193  vpImageConvert::vpCgb[index] = static_cast<int>(-89.8779 * aux) >> 8;
4194  vpImageConvert::vpCgr[index] = static_cast<int>(-185.8154 * aux) >> 8;
4195  vpImageConvert::vpCbb[index] = static_cast<int>(460.5724 * aux) >> 8;
4196  }
4197 
4198  YCbCrLUTcomputed = true;
4199  }
4200 }
4201 
4223 void vpImageConvert::YCbCrToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
4224 {
4225  unsigned char *cbv;
4226  unsigned char *crv;
4227  unsigned char *pt_ycbcr = ycbcr;
4228  unsigned char *pt_rgb = rgb;
4229  cbv = pt_ycbcr + 1;
4230  crv = pt_ycbcr + 3;
4231 
4232  vpImageConvert::computeYCbCrLUT();
4233 
4234  int col = 0;
4235 
4236  while (size--) {
4237  int val_r, val_g, val_b;
4238  if (!(col++ % 2)) {
4239  cbv = pt_ycbcr + 1;
4240  crv = pt_ycbcr + 3;
4241  }
4242 
4243  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4244  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4245  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4246 
4247  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4248 
4249  *pt_rgb++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4250  *pt_rgb++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4251  *pt_rgb++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4252 
4253  pt_ycbcr += 2;
4254  }
4255 }
4256 
4282 void vpImageConvert::YCbCrToRGBa(unsigned char *ycbcr, unsigned char *rgba, unsigned int size)
4283 {
4284  unsigned char *cbv;
4285  unsigned char *crv;
4286  unsigned char *pt_ycbcr = ycbcr;
4287  unsigned char *pt_rgba = rgba;
4288  cbv = pt_ycbcr + 1;
4289  crv = pt_ycbcr + 3;
4290 
4291  vpImageConvert::computeYCbCrLUT();
4292 
4293  int col = 0;
4294 
4295  while (size--) {
4296  int val_r, val_g, val_b;
4297  if (!(col++ % 2)) {
4298  cbv = pt_ycbcr + 1;
4299  crv = pt_ycbcr + 3;
4300  }
4301 
4302  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4303  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4304  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4305 
4306  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4307 
4308  *pt_rgba++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4309  *pt_rgba++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4310  *pt_rgba++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4311  *pt_rgba++ = vpRGBa::alpha_default;
4312 
4313  pt_ycbcr += 2;
4314  }
4315 }
4316 
4336 void vpImageConvert::YCbCrToGrey(unsigned char *ycbcr, unsigned char *grey, unsigned int size)
4337 {
4338  unsigned int i = 0, j = 0;
4339  const unsigned int doubleSize = size * 2;
4340  while (j < doubleSize) {
4341  grey[i++] = ycbcr[j];
4342  grey[i++] = ycbcr[j + 2];
4343  j += 4;
4344  }
4345 }
4346 
4368 void vpImageConvert::YCrCbToRGB(unsigned char *ycrcb, unsigned char *rgb, unsigned int size)
4369 {
4370  unsigned char *cbv;
4371  unsigned char *crv;
4372  unsigned char *pt_ycbcr = ycrcb;
4373  unsigned char *pt_rgb = rgb;
4374  crv = pt_ycbcr + 1;
4375  cbv = pt_ycbcr + 3;
4376 
4377  vpImageConvert::computeYCbCrLUT();
4378 
4379  int col = 0;
4380 
4381  while (size--) {
4382  int val_r, val_g, val_b;
4383  if (!(col++ % 2)) {
4384  crv = pt_ycbcr + 1;
4385  cbv = pt_ycbcr + 3;
4386  }
4387 
4388  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4389  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4390  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4391 
4392  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4393 
4394  *pt_rgb++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4395  *pt_rgb++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4396  *pt_rgb++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4397 
4398  pt_ycbcr += 2;
4399  }
4400 }
4401 
4426 void vpImageConvert::YCrCbToRGBa(unsigned char *ycrcb, unsigned char *rgba, unsigned int size)
4427 {
4428  unsigned char *cbv;
4429  unsigned char *crv;
4430  unsigned char *pt_ycbcr = ycrcb;
4431  unsigned char *pt_rgba = rgba;
4432  crv = pt_ycbcr + 1;
4433  cbv = pt_ycbcr + 3;
4434 
4435  vpImageConvert::computeYCbCrLUT();
4436 
4437  int col = 0;
4438 
4439  while (size--) {
4440  int val_r, val_g, val_b;
4441  if (!(col++ % 2)) {
4442  crv = pt_ycbcr + 1;
4443  cbv = pt_ycbcr + 3;
4444  }
4445 
4446  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4447  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4448  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4449 
4450  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
4451 
4452  *pt_rgba++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
4453  *pt_rgba++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
4454  *pt_rgba++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
4455  *pt_rgba++ = vpRGBa::alpha_default;
4456 
4457  pt_ycbcr += 2;
4458  }
4459 }
4460 
4501 {
4502 #if defined(VISP_HAVE_SIMDLIB)
4503  if (src.getSize() > 0) {
4504  if (pR) {
4505  pR->resize(src.getHeight(), src.getWidth());
4506  }
4507  if (pG) {
4508  pG->resize(src.getHeight(), src.getWidth());
4509  }
4510  if (pB) {
4511  pB->resize(src.getHeight(), src.getWidth());
4512  }
4513  if (pa) {
4514  pa->resize(src.getHeight(), src.getWidth());
4515  }
4516 
4517  unsigned char *ptrR = pR ? pR->bitmap : new unsigned char[src.getSize()];
4518  unsigned char *ptrG = pG ? pG->bitmap : new unsigned char[src.getSize()];
4519  unsigned char *ptrB = pB ? pB->bitmap : new unsigned char[src.getSize()];
4520  unsigned char *ptrA = pa ? pa->bitmap : new unsigned char[src.getSize()];
4521 
4522  SimdDeinterleaveBgra(reinterpret_cast<unsigned char *>(src.bitmap), src.getWidth() * sizeof(vpRGBa), src.getWidth(),
4523  src.getHeight(), ptrR, src.getWidth(), ptrG, src.getWidth(), ptrB, src.getWidth(), ptrA,
4524  src.getWidth());
4525 
4526  if (!pR) {
4527  delete [] ptrR;
4528  }
4529  if (!pG) {
4530  delete [] ptrG;
4531  }
4532  if (!pB) {
4533  delete [] ptrB;
4534  }
4535  if (!pa) {
4536  delete [] ptrA;
4537  }
4538  }
4539 #else
4540  size_t n = src.getNumberOfPixel();
4541  unsigned int height = src.getHeight();
4542  unsigned int width = src.getWidth();
4543  unsigned char *input;
4544  unsigned char *dst;
4545 
4546  vpImage<unsigned char> *tabChannel[4];
4547 
4548  /* incrsrc[0] = 0; //init
4549  incrsrc[1] = 0; //step after the first used channel
4550  incrsrc[2] = 0; //step after the second used channel
4551  incrsrc[3] = 0;
4552  incrsrc[4] = 0;
4553  */
4554  tabChannel[0] = pR;
4555  tabChannel[1] = pG;
4556  tabChannel[2] = pB;
4557  tabChannel[3] = pa;
4558 
4559  size_t i; /* ordre */
4560  for (unsigned int j = 0; j < 4; ++j) {
4561  if (tabChannel[j] != nullptr) {
4562  if ((tabChannel[j]->getHeight() != height) || (tabChannel[j]->getWidth() != width)) {
4563  tabChannel[j]->resize(height, width);
4564  }
4565  dst = (unsigned char *)tabChannel[j]->bitmap;
4566 
4567  input = (unsigned char *)src.bitmap + j;
4568  i = 0;
4569  // optimization
4570  if (n >= 4) {
4571  n -= 3;
4572  for (; i < n; i += 4) {
4573  *dst = *input;
4574  input += 4;
4575  dst++;
4576  *dst = *input;
4577  input += 4;
4578  dst++;
4579  *dst = *input;
4580  input += 4;
4581  dst++;
4582  *dst = *input;
4583  input += 4;
4584  dst++;
4585  }
4586  n += 3;
4587  }
4588 
4589  for (; i < n; ++i) {
4590  *dst = *input;
4591  input += 4;
4592  dst++;
4593  }
4594  }
4595  }
4596 #endif
4597 }
4598 
4611 {
4612  // Check if the input channels have all the same dimensions
4613  std::map<unsigned int, unsigned int> mapOfWidths, mapOfHeights;
4614  if (R != nullptr) {
4615  mapOfWidths[R->getWidth()]++;
4616  mapOfHeights[R->getHeight()]++;
4617  }
4618 
4619  if (G != nullptr) {
4620  mapOfWidths[G->getWidth()]++;
4621  mapOfHeights[G->getHeight()]++;
4622  }
4623 
4624  if (B != nullptr) {
4625  mapOfWidths[B->getWidth()]++;
4626  mapOfHeights[B->getHeight()]++;
4627  }
4628 
4629  if (a != nullptr) {
4630  mapOfWidths[a->getWidth()]++;
4631  mapOfHeights[a->getHeight()]++;
4632  }
4633 
4634  if ((mapOfWidths.size() == 1) && (mapOfHeights.size() == 1)) {
4635  unsigned int width = mapOfWidths.begin()->first;
4636  unsigned int height = mapOfHeights.begin()->first;
4637 
4638  RGBa.resize(height, width);
4639 
4640 
4641 #if defined(VISP_HAVE_SIMDLIB)
4642  if ((R != nullptr) && (G != nullptr) && (B != nullptr) && (a != nullptr)) {
4643  SimdInterleaveBgra(R->bitmap, width, G->bitmap, width, B->bitmap, width, a->bitmap, width, width, height,
4644  reinterpret_cast<uint8_t *>(RGBa.bitmap), width * sizeof(vpRGBa));
4645  }
4646  else {
4647 #endif
4648  unsigned int size = width * height;
4649  for (unsigned int i = 0; i < size; ++i) {
4650  if (R != nullptr) {
4651  RGBa.bitmap[i].R = R->bitmap[i];
4652  }
4653 
4654  if (G != nullptr) {
4655  RGBa.bitmap[i].G = G->bitmap[i];
4656  }
4657 
4658  if (B != nullptr) {
4659  RGBa.bitmap[i].B = B->bitmap[i];
4660  }
4661 
4662  if (a != nullptr) {
4663  RGBa.bitmap[i].A = a->bitmap[i];
4664  }
4665  }
4666 #if defined(VISP_HAVE_SIMDLIB)
4667  }
4668 #endif
4669  }
4670  else {
4671  throw vpException(vpException::dimensionError, "Mismatched dimensions!");
4672  }
4673 }
4674 
4685 void vpImageConvert::MONO16ToGrey(unsigned char *grey16, unsigned char *grey, unsigned int size)
4686 {
4687  int i = (((int)size) << 1) - 1;
4688  int j = (int)size - 1;
4689 
4690  while (i >= 0) {
4691  int y = grey16[i--];
4692  grey[j--] = static_cast<unsigned char>((y + (grey16[i--] << 8)) >> 8);
4693  }
4694 }
4695 
4707 void vpImageConvert::MONO16ToRGBa(unsigned char *grey16, unsigned char *rgba, unsigned int size)
4708 {
4709  int i = (((int)size) << 1) - 1;
4710  int j = static_cast<int>(size * 4 - 1);
4711 
4712  while (i >= 0) {
4713  int y = grey16[i--];
4714  unsigned char v = static_cast<unsigned char>((y + (grey16[i--] << 8)) >> 8);
4715  rgba[j--] = vpRGBa::alpha_default;
4716  rgba[j--] = v;
4717  rgba[j--] = v;
4718  rgba[j--] = v;
4719  }
4720 }
4721 
4732 void vpImageConvert::HSV2RGB(const double *hue_, const double *saturation_, const double *value_, unsigned char *rgb,
4733  unsigned int size, unsigned int step)
4734 {
4735  for (unsigned int i = 0; i < size; ++i) {
4736  double hue = hue_[i], saturation = saturation_[i], value = value_[i];
4737 
4738  if (vpMath::equal(saturation, 0.0, std::numeric_limits<double>::epsilon())) {
4739  hue = value;
4740  saturation = value;
4741  }
4742  else {
4743  double h = hue * 6.0;
4744  double s = saturation;
4745  double v = value;
4746 
4747  if (vpMath::equal(h, 6.0, std::numeric_limits<double>::epsilon())) {
4748  h = 0.0;
4749  }
4750 
4751  double f = h - static_cast<int>(h);
4752  double p = v * (1.0 - s);
4753  double q = v * (1.0 - (s * f));
4754  double t = v * (1.0 - (s * (1.0 - f)));
4755 
4756  switch (static_cast<int>(h)) {
4757  case 0:
4758  hue = v;
4759  saturation = t;
4760  value = p;
4761  break;
4762 
4763  case 1:
4764  hue = q;
4765  saturation = v;
4766  value = p;
4767  break;
4768 
4769  case 2:
4770  hue = p;
4771  saturation = v;
4772  value = t;
4773  break;
4774 
4775  case 3:
4776  hue = p;
4777  saturation = q;
4778  value = v;
4779  break;
4780 
4781  case 4:
4782  hue = t;
4783  saturation = p;
4784  value = v;
4785  break;
4786 
4787  default: // case 5:
4788  hue = v;
4789  saturation = p;
4790  value = q;
4791  break;
4792  }
4793  }
4794 
4795  rgb[i * step] = static_cast<unsigned char>(vpMath::round(hue * 255.0));
4796  rgb[i * step + 1] = static_cast<unsigned char>(vpMath::round(saturation * 255.0));
4797  rgb[i * step + 2] = static_cast<unsigned char>(vpMath::round(value * 255.0));
4798  if (step == 4) {// alpha
4799  rgb[i * step + 3] = vpRGBa::alpha_default;
4800  }
4801  }
4802 }
4803 
4814 void vpImageConvert::RGB2HSV(const unsigned char *rgb, double *hue, double *saturation, double *value,
4815  unsigned int size, unsigned int step)
4816 {
4817  for (unsigned int i = 0; i < size; ++i) {
4818  double red, green, blue;
4819  double h, s, v;
4820  double min, max;
4821 
4822  red = rgb[i * step] / 255.0;
4823  green = rgb[i * step + 1] / 255.0;
4824  blue = rgb[i * step + 2] / 255.0;
4825 
4826  if (red > green) {
4827  max = ((std::max))(red, blue);
4828  min = ((std::min))(green, blue);
4829  }
4830  else {
4831  max = ((std::max))(green, blue);
4832  min = ((std::min))(red, blue);
4833  }
4834 
4835  v = max;
4836 
4837  if (!vpMath::equal(max, 0.0, std::numeric_limits<double>::epsilon())) {
4838  s = (max - min) / max;
4839  }
4840  else {
4841  s = 0.0;
4842  }
4843 
4844  if (vpMath::equal(s, 0.0, std::numeric_limits<double>::epsilon())) {
4845  h = 0.0;
4846  }
4847  else {
4848  double delta = max - min;
4849  if (vpMath::equal(delta, 0.0, std::numeric_limits<double>::epsilon())) {
4850  delta = 1.0;
4851  }
4852 
4853  if (vpMath::equal(red, max, std::numeric_limits<double>::epsilon())) {
4854  h = (green - blue) / delta;
4855  }
4856  else if (vpMath::equal(green, max, std::numeric_limits<double>::epsilon())) {
4857  h = 2 + (blue - red) / delta;
4858  }
4859  else {
4860  h = 4 + (red - green) / delta;
4861  }
4862 
4863  h /= 6.0;
4864  if (h < 0.0) {
4865  h += 1.0;
4866  }
4867  else if (h > 1.0) {
4868  h -= 1.0;
4869  }
4870  }
4871 
4872  hue[i] = h;
4873  saturation[i] = s;
4874  value[i] = v;
4875  }
4876 }
4877 
4890 void vpImageConvert::HSVToRGBa(const double *hue, const double *saturation, const double *value, unsigned char *rgba,
4891  unsigned int size)
4892 {
4893  vpImageConvert::HSV2RGB(hue, saturation, value, rgba, size, 4);
4894 }
4895 
4908 void vpImageConvert::HSVToRGBa(const unsigned char *hue, const unsigned char *saturation, const unsigned char *value,
4909  unsigned char *rgba, unsigned int size)
4910 {
4911  for (unsigned int i = 0; i < size; ++i) {
4912  double h = hue[i] / 255.0, s = saturation[i] / 255.0, v = value[i] / 255.0;
4913 
4914  vpImageConvert::HSVToRGBa(&h, &s, &v, (rgba + (i * 4)), 1);
4915  }
4916 }
4917 
4930 void vpImageConvert::RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value,
4931  unsigned int size)
4932 {
4933  vpImageConvert::RGB2HSV(rgba, hue, saturation, value, size, 4);
4934 }
4935 
4947 void vpImageConvert::RGBaToHSV(const unsigned char *rgba, unsigned char *hue, unsigned char *saturation,
4948  unsigned char *value, unsigned int size)
4949 {
4950  for (unsigned int i = 0; i < size; ++i) {
4951  double h, s, v;
4952  vpImageConvert::RGBaToHSV((rgba + (i * 4)), &h, &s, &v, 1);
4953 
4954  hue[i] = static_cast<unsigned char>(255.0 * h);
4955  saturation[i] = static_cast<unsigned char>(255.0 * s);
4956  value[i] = static_cast<unsigned char>(255.0 * v);
4957  }
4958 }
4959 
4970 void vpImageConvert::HSVToRGB(const double *hue, const double *saturation, const double *value, unsigned char *rgb,
4971  unsigned int size)
4972 {
4973  vpImageConvert::HSV2RGB(hue, saturation, value, rgb, size, 3);
4974 }
4975 
4985 void vpImageConvert::HSVToRGB(const unsigned char *hue, const unsigned char *saturation, const unsigned char *value,
4986  unsigned char *rgb, unsigned int size)
4987 {
4988  for (unsigned int i = 0; i < size; ++i) {
4989  double h = hue[i] / 255.0, s = saturation[i] / 255.0, v = value[i] / 255.0;
4990 
4991  vpImageConvert::HSVToRGB(&h, &s, &v, (rgb + (i * 3)), 1);
4992  }
4993 }
4994 
5004 void vpImageConvert::RGBToHSV(const unsigned char *rgb, double *hue, double *saturation, double *value,
5005  unsigned int size)
5006 {
5007  vpImageConvert::RGB2HSV(rgb, hue, saturation, value, size, 3);
5008 }
5009 
5019 void vpImageConvert::RGBToHSV(const unsigned char *rgb, unsigned char *hue, unsigned char *saturation,
5020  unsigned char *value, unsigned int size)
5021 {
5022  for (unsigned int i = 0; i < size; ++i) {
5023  double h, s, v;
5024 
5025  vpImageConvert::RGBToHSV((rgb + (i * 3)), &h, &s, &v, 1);
5026 
5027  hue[i] = static_cast<unsigned char>(255.0 * h);
5028  saturation[i] = static_cast<unsigned char>(255.0 * s);
5029  value[i] = static_cast<unsigned char>(255.0 * v);
5030  }
5031 }
5032 
5033 // Bilinear
5034 
5047 void vpImageConvert::demosaicBGGRToRGBaBilinear(const uint8_t *bggr, uint8_t *rgba, unsigned int width,
5048  unsigned int height, unsigned int nThreads)
5049 {
5050  demosaicBGGRToRGBaBilinearTpl(bggr, rgba, width, height, nThreads);
5051 }
5052 
5065 void vpImageConvert::demosaicBGGRToRGBaBilinear(const uint16_t *bggr, uint16_t *rgba, unsigned int width,
5066  unsigned int height, unsigned int nThreads)
5067 {
5068  demosaicBGGRToRGBaBilinearTpl(bggr, rgba, width, height, nThreads);
5069 }
5070 
5083 void vpImageConvert::demosaicGBRGToRGBaBilinear(const uint8_t *gbrg, uint8_t *rgba, unsigned int width,
5084  unsigned int height, unsigned int nThreads)
5085 {
5086  demosaicGBRGToRGBaBilinearTpl(gbrg, rgba, width, height, nThreads);
5087 }
5088 
5101 void vpImageConvert::demosaicGBRGToRGBaBilinear(const uint16_t *gbrg, uint16_t *rgba, unsigned int width,
5102  unsigned int height, unsigned int nThreads)
5103 {
5104  demosaicGBRGToRGBaBilinearTpl(gbrg, rgba, width, height, nThreads);
5105 }
5106 
5119 void vpImageConvert::demosaicGRBGToRGBaBilinear(const uint8_t *grbg, uint8_t *rgba, unsigned int width,
5120  unsigned int height, unsigned int nThreads)
5121 {
5122  demosaicGRBGToRGBaBilinearTpl(grbg, rgba, width, height, nThreads);
5123 }
5124 
5137 void vpImageConvert::demosaicGRBGToRGBaBilinear(const uint16_t *grbg, uint16_t *rgba, unsigned int width,
5138  unsigned int height, unsigned int nThreads)
5139 {
5140  demosaicGRBGToRGBaBilinearTpl(grbg, rgba, width, height, nThreads);
5141 }
5142 
5155 void vpImageConvert::demosaicRGGBToRGBaBilinear(const uint8_t *rggb, uint8_t *rgba, unsigned int width,
5156  unsigned int height, unsigned int nThreads)
5157 {
5158  demosaicRGGBToRGBaBilinearTpl(rggb, rgba, width, height, nThreads);
5159 }
5160 
5173 void vpImageConvert::demosaicRGGBToRGBaBilinear(const uint16_t *rggb, uint16_t *rgba, unsigned int width,
5174  unsigned int height, unsigned int nThreads)
5175 {
5176  demosaicRGGBToRGBaBilinearTpl(rggb, rgba, width, height, nThreads);
5177 }
5178 
5179 // Malvar
5180 
5193 void vpImageConvert::demosaicBGGRToRGBaMalvar(const uint8_t *bggr, uint8_t *rgba, unsigned int width,
5194  unsigned int height, unsigned int nThreads)
5195 {
5196  demosaicBGGRToRGBaMalvarTpl(bggr, rgba, width, height, nThreads);
5197 }
5198 
5211 void vpImageConvert::demosaicBGGRToRGBaMalvar(const uint16_t *bggr, uint16_t *rgba, unsigned int width,
5212  unsigned int height, unsigned int nThreads)
5213 {
5214  demosaicBGGRToRGBaMalvarTpl(bggr, rgba, width, height, nThreads);
5215 }
5216 
5229 void vpImageConvert::demosaicGBRGToRGBaMalvar(const uint8_t *gbrg, uint8_t *rgba, unsigned int width,
5230  unsigned int height, unsigned int nThreads)
5231 {
5232  demosaicGBRGToRGBaMalvarTpl(gbrg, rgba, width, height, nThreads);
5233 }
5234 
5247 void vpImageConvert::demosaicGBRGToRGBaMalvar(const uint16_t *gbrg, uint16_t *rgba, unsigned int width,
5248  unsigned int height, unsigned int nThreads)
5249 {
5250  demosaicGBRGToRGBaMalvarTpl(gbrg, rgba, width, height, nThreads);
5251 }
5252 
5265 void vpImageConvert::demosaicGRBGToRGBaMalvar(const uint8_t *grbg, uint8_t *rgba, unsigned int width,
5266  unsigned int height, unsigned int nThreads)
5267 {
5268  demosaicGRBGToRGBaMalvarTpl(grbg, rgba, width, height, nThreads);
5269 }
5270 
5283 void vpImageConvert::demosaicGRBGToRGBaMalvar(const uint16_t *grbg, uint16_t *rgba, unsigned int width,
5284  unsigned int height, unsigned int nThreads)
5285 {
5286  demosaicGRBGToRGBaMalvarTpl(grbg, rgba, width, height, nThreads);
5287 }
5288 
5301 void vpImageConvert::demosaicRGGBToRGBaMalvar(const uint8_t *rggb, uint8_t *rgba, unsigned int width,
5302  unsigned int height, unsigned int nThreads)
5303 {
5304  demosaicRGGBToRGBaMalvarTpl(rggb, rgba, width, height, nThreads);
5305 }
5306 
5319 void vpImageConvert::demosaicRGGBToRGBaMalvar(const uint16_t *rggb, uint16_t *rgba, unsigned int width,
5320  unsigned int height, unsigned int nThreads)
5321 {
5322  demosaicRGGBToRGBaMalvarTpl(rggb, rgba, width, height, nThreads);
5323 }
error that can be emitted by ViSP classes.
Definition: vpException.h:59
@ badValue
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:85
@ dimensionError
Bad dimension.
Definition: vpException.h:83
@ fatalError
Fatal error.
Definition: vpException.h:84
static void YUV411ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void YVU9ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void MONO16ToGrey(unsigned char *grey16, unsigned char *grey, unsigned int size)
static void HSVToRGBa(const double *hue, const double *saturation, const double *value, unsigned char *rgba, unsigned int size)
static void YUYVToRGBa(unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height)
static void demosaicBGGRToRGBaBilinear(const uint8_t *bggr, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void demosaicGRBGToRGBaBilinear(const uint8_t *grbg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void RGBToHSV(const unsigned char *rgb, double *hue, double *saturation, double *value, unsigned int size)
static void demosaicGRBGToRGBaMalvar(const uint8_t *grbg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void YUV422ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void YUV420ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
static void YUV411ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
static void YUV420ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void demosaicGBRGToRGBaMalvar(const uint8_t *gbrg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void YVU9ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
static void merge(const vpImage< unsigned char > *R, const vpImage< unsigned char > *G, const vpImage< unsigned char > *B, const vpImage< unsigned char > *a, vpImage< vpRGBa > &RGBa)
static void YV12ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YUV444ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
static void demosaicBGGRToRGBaMalvar(const uint8_t *bggr, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void YUV411ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
static void YUVToRGB(unsigned char y, unsigned char u, unsigned char v, unsigned char &r, unsigned char &g, unsigned char &b)
static void demosaicGBRGToRGBaBilinear(const uint8_t *gbrg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void YCbCrToGrey(unsigned char *ycbcr, unsigned char *grey, 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=nullptr)
static void YUV422ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
static void YCrCbToRGB(unsigned char *ycrcb, unsigned char *rgb, unsigned int size)
static void YCbCrToRGBa(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void createDepthHistogram(const vpImage< uint16_t > &src_depth, vpImage< vpRGBa > &dest_rgba)
static void RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value, unsigned int size)
static void demosaicRGGBToRGBaMalvar(const uint8_t *rggb, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int width, unsigned int height)
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static void MONO16ToRGBa(unsigned char *grey16, unsigned char *rgba, unsigned int size)
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false)
static void RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void GreyToRGB(unsigned char *grey, unsigned char *rgb, unsigned int size)
static void YCrCbToRGBa(unsigned char *ycrcb, unsigned char *rgb, unsigned int size)
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
static void YCbCrToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void BGRaToGrey(unsigned char *bgra, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static void YUV422ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
static void YV12ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static void BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static void demosaicRGGBToRGBaBilinear(const uint8_t *rggb, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void YUV444ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
static void BGRaToRGBa(unsigned char *bgra, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static void RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
static void YUV444ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void YUV420ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
static void HSVToRGB(const double *hue, const double *saturation, const double *value, unsigned char *rgb, unsigned int size)
static void YUYVToRGB(unsigned char *yuyv, unsigned char *rgb, unsigned int width, unsigned int height)
unsigned int getWidth() const
Definition: vpImage.h:249
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:787
unsigned int getNumberOfPixel() const
Definition: vpImage.h:211
unsigned int getSize() const
Definition: vpImage.h:229
unsigned int getCols() const
Definition: vpImage.h:175
Type * bitmap
points toward the bitmap
Definition: vpImage.h:139
unsigned int getHeight() const
Definition: vpImage.h:184
unsigned int getRows() const
Definition: vpImage.h:220
void getMinMaxValue(Type &min, Type &max, bool onlyFiniteVal=true) const
Look for the minimum and the maximum value within the bitmap.
Definition: vpImage.h:1282
static bool equal(double x, double y, double threshold=0.001)
Definition: vpMath.h:449
static int round(double x)
Definition: vpMath.h:403
Definition: vpRGBa.h:61
unsigned char B
Blue component.
Definition: vpRGBa.h:139
unsigned char R
Red component.
Definition: vpRGBa.h:137
unsigned char G
Green component.
Definition: vpRGBa.h:138
@ alpha_default
Definition: vpRGBa.h:63
unsigned char A
Additionnal component.
Definition: vpRGBa.h:140
Definition: vpRGBf.h:57
float B
Blue component.
Definition: vpRGBf.h:126
float G
Green component.
Definition: vpRGBf.h:125
float R
Red component.
Definition: vpRGBf.h:124
#define vpDEBUG_TRACE
Definition: vpDebug.h:473