Visual Servoing Platform  version 3.3.1 under development (2020-08-10)
vpImageConvert.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Convert image types.
33  *
34  * Authors:
35  * Eric Marchand
36  * Fabien Spindler
37  * Anthony Saunier
38  *
39  *****************************************************************************/
40 
46 #include <map>
47 #include <sstream>
48 
49 #if defined _OPENMP
50 #include <omp.h>
51 #endif
52 
53 // image
54 #include <visp3/core/vpImageConvert.h>
55 #include <Simd/SimdLib.hpp>
56 
57 bool vpImageConvert::YCbCrLUTcomputed = false;
58 int vpImageConvert::vpCrr[256];
59 int vpImageConvert::vpCgb[256];
60 int vpImageConvert::vpCgr[256];
61 int vpImageConvert::vpCbb[256];
62 
72 {
73  dest.resize(src.getHeight(), src.getWidth());
74 
75  GreyToRGBa(src.bitmap, reinterpret_cast<unsigned char*>(dest.bitmap), src.getWidth(), src.getHeight());
76 }
77 
87 void vpImageConvert::convert(const vpImage<vpRGBa> &src, vpImage<unsigned char> &dest, unsigned int nThreads)
88 {
89  dest.resize(src.getHeight(), src.getWidth());
90 
91  RGBaToGrey(reinterpret_cast<unsigned char*>(src.bitmap), dest.bitmap, src.getWidth(),
92  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  else if (val > 255)
114  dest.bitmap[i] = 255;
115  else
116  dest.bitmap[i] = (unsigned char)val;
117  }
118 }
119 
126 {
127  dest.resize(src.getHeight(), src.getWidth());
128  for (unsigned int i = 0; i < src.getHeight() * src.getWidth(); i++)
129  dest.bitmap[i] = (float)src.bitmap[i];
130 }
131 
139 {
140  dest.resize(src.getHeight(), src.getWidth());
141  unsigned int max_xy = src.getWidth() * src.getHeight();
142  double min, max;
143 
144  src.getMinMaxValue(min, max);
145 
146  for (unsigned int i = 0; i < max_xy; i++) {
147  double val = 255. * (src.bitmap[i] - min) / (max - min);
148  if (val < 0)
149  dest.bitmap[i] = 0;
150  else if (val > 255)
151  dest.bitmap[i] = 255;
152  else
153  dest.bitmap[i] = (unsigned char)val;
154  }
155 }
156 
163 {
164  dest.resize(src.getHeight(), src.getWidth());
165 
166  for (unsigned int i = 0; i < src.getSize(); i++)
167  dest.bitmap[i] = (src.bitmap[i] >> 8);
168 }
169 
176 {
177  dest.resize(src.getHeight(), src.getWidth());
178 
179  for (unsigned int i = 0; i < src.getSize(); i++)
180  dest.bitmap[i] = static_cast<unsigned char>(src.bitmap[i] << 8);
181 }
182 
189 {
190  dest.resize(src.getHeight(), src.getWidth());
191  for (unsigned int i = 0; i < src.getHeight() * src.getWidth(); i++)
192  dest.bitmap[i] = (double)src.bitmap[i];
193 }
194 
203 {
204  dest_rgba.resize(src_depth.getHeight(), src_depth.getWidth());
205  static uint32_t histogram[0x10000];
206  memset(histogram, 0, sizeof(histogram));
207 
208  for (unsigned int i = 0; i < src_depth.getSize(); ++i)
209  ++histogram[src_depth.bitmap[i]];
210  for (int i = 2; i < 0x10000; ++i)
211  histogram[i] += histogram[i - 1]; // Build a cumulative histogram for the
212  // indices in [1,0xFFFF]
213 
214  for (unsigned int i = 0; i < src_depth.getSize(); ++i) {
215  uint16_t d = src_depth.bitmap[i];
216  if (d) {
217  unsigned char f = (unsigned char)(histogram[d] * 255 / histogram[0xFFFF]); // 0-255 based on histogram location
218  dest_rgba.bitmap[i].R = 255 - f;
219  dest_rgba.bitmap[i].G = 0;
220  dest_rgba.bitmap[i].B = f;
221  dest_rgba.bitmap[i].A = vpRGBa::alpha_default;
222  } else {
223  dest_rgba.bitmap[i].R = 20;
224  dest_rgba.bitmap[i].G = 5;
225  dest_rgba.bitmap[i].B = 0;
226  dest_rgba.bitmap[i].A = vpRGBa::alpha_default;
227  }
228  }
229 }
230 
238 {
239  dest_depth.resize(src_depth.getHeight(), src_depth.getWidth());
240  static uint32_t histogram2[0x10000];
241  memset(histogram2, 0, sizeof(histogram2));
242 
243  for (unsigned int i = 0; i < src_depth.getSize(); ++i)
244  ++histogram2[src_depth.bitmap[i]];
245  for (int i = 2; i < 0x10000; ++i)
246  histogram2[i] += histogram2[i - 1]; // Build a cumulative histogram for
247  // the indices in [1,0xFFFF]
248 
249  for (unsigned int i = 0; i < src_depth.getSize(); ++i) {
250  uint16_t d = src_depth.bitmap[i];
251  if (d) {
252  unsigned char f = static_cast<unsigned char>(histogram2[d] * 255 / histogram2[0xFFFF]); // 0-255 based on histogram location
253  dest_depth.bitmap[i] = f;
254  } else {
255  dest_depth.bitmap[i] = 0;
256  }
257  }
258 }
259 
260 #ifdef VISP_HAVE_OPENCV
261 // Deprecated: will be removed with OpenCV transcient from C to C++ api
307 void vpImageConvert::convert(const IplImage *src, vpImage<vpRGBa> &dest, bool flip)
308 {
309  int nChannel = src->nChannels;
310  int depth = src->depth;
311  int height = src->height;
312  int width = src->width;
313  int widthStep = src->widthStep;
314  int lineStep = (flip) ? 1 : 0;
315 
316  if (nChannel == 3 && depth == 8) {
317  dest.resize((unsigned int)height, (unsigned int)width);
318 
319  // starting source address
320  unsigned char *input = (unsigned char *)src->imageData;
321  unsigned char *beginOutput = (unsigned char *)dest.bitmap;
322 
323  for (int i = 0; i < height; i++) {
324  unsigned char *line = input;
325  unsigned char *output = beginOutput + lineStep * (4 * width * (height - 1 - i)) + (1 - lineStep) * 4 * width * i;
326  for (int j = 0; j < width; j++) {
327  *(output++) = *(line + 2);
328  *(output++) = *(line + 1);
329  *(output++) = *(line);
330  *(output++) = vpRGBa::alpha_default;
331 
332  line += 3;
333  }
334  // go to the next line
335  input += widthStep;
336  }
337  } else if (nChannel == 1 && depth == 8) {
338  dest.resize((unsigned int)height, (unsigned int)width);
339  // starting source address
340  unsigned char *input = (unsigned char *)src->imageData;
341  unsigned char *beginOutput = (unsigned char *)dest.bitmap;
342 
343  for (int i = 0; i < height; i++) {
344  unsigned char *line = input;
345  unsigned char *output = beginOutput + lineStep * (4 * width * (height - 1 - i)) + (1 - lineStep) * 4 * width * i;
346  for (int j = 0; j < width; j++) {
347  *output++ = *(line);
348  *output++ = *(line);
349  *output++ = *(line);
350  *output++ = vpRGBa::alpha_default; // alpha
351 
352  line++;
353  }
354  // go to the next line
355  input += widthStep;
356  }
357  }
358 }
359 
402 void vpImageConvert::convert(const IplImage *src, vpImage<unsigned char> &dest, bool flip)
403 {
404  int nChannel = src->nChannels;
405  int depth = src->depth;
406  int height = src->height;
407  int width = src->width;
408  int widthStep = src->widthStep;
409  int lineStep = (flip) ? 1 : 0;
410 
411  if (flip == false) {
412  if (widthStep == width) {
413  if (nChannel == 1 && depth == 8) {
414  dest.resize((unsigned int)height, (unsigned int)width);
415  memcpy(dest.bitmap, src->imageData, (size_t)(height * width));
416  }
417  if (nChannel == 3 && depth == 8) {
418  dest.resize((unsigned int)height, (unsigned int)width);
419  BGRToGrey((unsigned char *)src->imageData, dest.bitmap, (unsigned int)width, (unsigned int)height, false);
420  }
421  } else {
422  if (nChannel == 1 && depth == 8) {
423  dest.resize((unsigned int)height, (unsigned int)width);
424  for (int i = 0; i < height; i++) {
425  memcpy(dest.bitmap + i * width, src->imageData + i * widthStep, (size_t)width);
426  }
427  }
428  if (nChannel == 3 && depth == 8) {
429  dest.resize((unsigned int)height, (unsigned int)width);
430  for (int i = 0; i < height; i++) {
431  BGRToGrey((unsigned char *)src->imageData + i * widthStep, dest.bitmap + i * width, (unsigned int)width, 1,
432  false);
433  }
434  }
435  }
436  } else {
437  if (nChannel == 1 && depth == 8) {
438  dest.resize((unsigned int)height, (unsigned int)width);
439  unsigned char *beginOutput = (unsigned char *)dest.bitmap;
440  for (int i = 0; i < height; i++) {
441  memcpy(beginOutput + lineStep * (4 * width * (height - 1 - i)), src->imageData + i * widthStep, (size_t)width);
442  }
443  }
444  if (nChannel == 3 && depth == 8) {
445  dest.resize((unsigned int)height, (unsigned int)width);
446  // for (int i = 0 ; i < height ; i++){
447  BGRToGrey((unsigned char *)src->imageData /*+ i*widthStep*/, dest.bitmap /*+ i*width*/, (unsigned int)width,
448  (unsigned int)height /*1*/, true);
449  //}
450  }
451  }
452 }
453 
497 void vpImageConvert::convert(const vpImage<vpRGBa> &src, IplImage *&dest)
498 {
499  int height = (int)src.getHeight();
500  int width = (int)src.getWidth();
501  CvSize size = cvSize(width, height);
502  int depth = 8;
503  int channels = 3;
504  if (dest != NULL) {
505  if (dest->nChannels != channels || dest->depth != depth || dest->height != height || dest->width != width) {
506  if (dest->nChannels != 0)
507  cvReleaseImage(&dest);
508  dest = cvCreateImage(size, depth, channels);
509  }
510  } else
511  dest = cvCreateImage(size, depth, channels);
512 
513  // starting source address
514  unsigned char *input = (unsigned char *)src.bitmap; // rgba image
515  unsigned char *output = (unsigned char *)dest->imageData; // bgr image
516 
517  int j = 0;
518  int i = 0;
519  int widthStep = dest->widthStep;
520 
521  for (i = 0; i < height; i++) {
522  output = (unsigned char *)dest->imageData + i * widthStep;
523  unsigned char *line = input;
524  for (j = 0; j < width; j++) {
525  *output++ = *(line + 2); // B
526  *output++ = *(line + 1); // G
527  *output++ = *(line); // R
528 
529  line += 4;
530  }
531  // go to the next line
532  input += 4 * width;
533  }
534 }
535 
579 void vpImageConvert::convert(const vpImage<unsigned char> &src, IplImage *&dest)
580 {
581  unsigned int height = src.getHeight();
582  unsigned int width = src.getWidth();
583  CvSize size = cvSize((int)width, (int)height);
584  int depth = 8;
585  int channels = 1;
586  if (dest != NULL) {
587  if (dest->nChannels != channels || dest->depth != depth || dest->height != (int)height ||
588  dest->width != (int)width) {
589  if (dest->nChannels != 0)
590  cvReleaseImage(&dest);
591  dest = cvCreateImage(size, depth, channels);
592  }
593  } else
594  dest = cvCreateImage(size, depth, channels);
595 
596  unsigned int widthStep = (unsigned int)dest->widthStep;
597 
598  if (width == widthStep) {
599  memcpy(dest->imageData, src.bitmap, width * height);
600  } else {
601  // copying each line taking account of the widthStep
602  for (unsigned int i = 0; i < height; i++) {
603  memcpy(dest->imageData + i * widthStep, src.bitmap + i * width, width);
604  }
605  }
606 }
607 
608 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
609 
656 void vpImageConvert::convert(const cv::Mat &src, vpImage<vpRGBa> &dest, bool flip)
657 {
658 dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
659 
660  if (src.type() == CV_8UC4) {
661  vpRGBa rgbaVal;
662  for (unsigned int i = 0; i < dest.getRows(); ++i)
663  for (unsigned int j = 0; j < dest.getCols(); ++j) {
664  cv::Vec4b tmp = src.at<cv::Vec4b>((int)i, (int)j);
665  rgbaVal.R = tmp[2];
666  rgbaVal.G = tmp[1];
667  rgbaVal.B = tmp[0];
668  rgbaVal.A = tmp[3];
669  if (flip)
670  dest[dest.getRows() - i - 1][j] = rgbaVal;
671  else
672  dest[i][j] = rgbaVal;
673  }
674  } else if (src.type() == CV_8UC3) {
675  if (src.isContinuous() && !flip) {
676  SimdBgrToRgba(src.data, src.cols, src.rows, src.step[0], reinterpret_cast<uint8_t*>(dest.bitmap),
677  dest.getWidth() * sizeof(vpRGBa), vpRGBa::alpha_default);
678  } else {
679  vpRGBa rgbaVal;
680  rgbaVal.A = vpRGBa::alpha_default;
681  for (unsigned int i = 0; i < dest.getRows(); ++i) {
682  for (unsigned int j = 0; j < dest.getCols(); ++j) {
683  cv::Vec3b tmp = src.at<cv::Vec3b>((int)i, (int)j);
684  rgbaVal.R = tmp[2];
685  rgbaVal.G = tmp[1];
686  rgbaVal.B = tmp[0];
687  if (flip) {
688  dest[dest.getRows() - i - 1][j] = rgbaVal;
689  } else {
690  dest[i][j] = rgbaVal;
691  }
692  }
693  }
694  }
695  } else if (src.type() == CV_8UC1) {
696  if (src.isContinuous() && !flip) {
697  SimdGrayToBgra(src.data, src.cols, src.rows, src.step[0], reinterpret_cast<uint8_t*>(dest.bitmap),
698  dest.getWidth() * sizeof(vpRGBa), vpRGBa::alpha_default);
699  } else {
700  vpRGBa rgbaVal;
701  for (unsigned int i = 0; i < dest.getRows(); ++i) {
702  for (unsigned int j = 0; j < dest.getCols(); ++j) {
703  rgbaVal = src.at<unsigned char>((int)i, (int)j);
704  if (flip) {
705  dest[dest.getRows() - i - 1][j] = rgbaVal;
706  } else {
707  dest[i][j] = rgbaVal;
708  }
709  }
710  }
711  }
712  }
713 }
714 
757 void vpImageConvert::convert(const cv::Mat &src, vpImage<unsigned char> &dest, bool flip,
758  unsigned int nThreads)
759 {
760  if (src.type() == CV_8UC1) {
761  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
762  if (src.isContinuous() && !flip) {
763  memcpy(dest.bitmap, src.data, (size_t)(src.rows * src.cols));
764  } else {
765  if (flip) {
766  for (unsigned int i = 0; i < dest.getRows(); ++i) {
767  memcpy(dest.bitmap + i * dest.getCols(), src.data + (dest.getRows() - i - 1) * src.step1(), (size_t)src.step);
768  }
769  } else {
770  for (unsigned int i = 0; i < dest.getRows(); ++i) {
771  memcpy(dest.bitmap + i * dest.getCols(), src.data + i * src.step1(), (size_t)src.step);
772  }
773  }
774  }
775  } else if (src.type() == CV_8UC3) {
776  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
777  if (src.isContinuous()) {
778  BGRToGrey((unsigned char *)src.data, (unsigned char *)dest.bitmap, (unsigned int)src.cols, (unsigned int)src.rows,
779  flip, nThreads);
780  } else {
781  if (flip) {
782  for (unsigned int i = 0; i < dest.getRows(); ++i) {
783  BGRToGrey((unsigned char *)src.data + i * src.step1(),
784  (unsigned char *)dest.bitmap + (dest.getRows() - i - 1) * dest.getCols(),
785  (unsigned int)dest.getCols(), 1, false);
786  }
787  } else {
788  for (unsigned int i = 0; i < dest.getRows(); ++i) {
789  BGRToGrey((unsigned char *)src.data + i * src.step1(), (unsigned char *)dest.bitmap + i * dest.getCols(),
790  (unsigned int)dest.getCols(), 1, false);
791  }
792  }
793  }
794  }
795 }
796 
833 void vpImageConvert::convert(const vpImage<vpRGBa> &src, cv::Mat &dest)
834 {
835  cv::Mat vpToMat((int)src.getRows(), (int)src.getCols(), CV_8UC4, (void *)src.bitmap);
836  cv::cvtColor(vpToMat, dest, cv::COLOR_RGBA2BGR);
837 }
838 
877 void vpImageConvert::convert(const vpImage<unsigned char> &src, cv::Mat &dest, bool copyData)
878 {
879  if (copyData) {
880  cv::Mat tmpMap((int)src.getRows(), (int)src.getCols(), CV_8UC1, (void *)src.bitmap);
881  dest = tmpMap.clone();
882  } else {
883  dest = cv::Mat((int)src.getRows(), (int)src.getCols(), CV_8UC1, (void *)src.bitmap);
884  }
885 }
886 
887 #endif
888 #endif
889 
890 #ifdef VISP_HAVE_YARP
891 
925 void vpImageConvert::convert(const vpImage<unsigned char> &src, yarp::sig::ImageOf<yarp::sig::PixelMono> *dest,
926  bool copyData)
927 {
928  if (copyData) {
929  dest->resize(src.getWidth(), src.getHeight());
930  memcpy(dest->getRawImage(), src.bitmap, src.getHeight() * src.getWidth());
931  } else
932  dest->setExternal(src.bitmap, (int)src.getCols(), (int)src.getRows());
933 }
934 
973 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelMono> *src, vpImage<unsigned char> &dest,
974  bool copyData)
975 {
976  dest.resize(src->height(), src->width());
977  if (copyData)
978  memcpy(dest.bitmap, src->getRawImage(), src->height() * src->width() * sizeof(yarp::sig::PixelMono));
979  else
980  dest.bitmap = src->getRawImage();
981 }
982 
1017 void vpImageConvert::convert(const vpImage<vpRGBa> &src, yarp::sig::ImageOf<yarp::sig::PixelRgba> *dest,
1018  bool copyData)
1019 {
1020  if (copyData) {
1021  dest->resize(src.getWidth(), src.getHeight());
1022  memcpy(dest->getRawImage(), src.bitmap, src.getHeight() * src.getWidth() * sizeof(vpRGBa));
1023  } else
1024  dest->setExternal(src.bitmap, (int)src.getCols(), (int)src.getRows());
1025 }
1026 
1065 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelRgba> *src, vpImage<vpRGBa> &dest,
1066  bool copyData)
1067 {
1068  dest.resize(src->height(), src->width());
1069  if (copyData)
1070  memcpy(dest.bitmap, src->getRawImage(), src->height() * src->width() * sizeof(yarp::sig::PixelRgba));
1071  else
1072  dest.bitmap = static_cast<vpRGBa *>(src->getRawImage());
1073 }
1074 
1107 void vpImageConvert::convert(const vpImage<vpRGBa> &src, yarp::sig::ImageOf<yarp::sig::PixelRgb> *dest)
1108 {
1109  dest->resize(src.getWidth(), src.getHeight());
1110  for (unsigned int i = 0; i < src.getRows(); i++) {
1111  for (unsigned int j = 0; j < src.getWidth(); j++) {
1112  dest->pixel(j, i).r = src[i][j].R;
1113  dest->pixel(j, i).g = src[i][j].G;
1114  dest->pixel(j, i).b = src[i][j].B;
1115  }
1116  }
1117 }
1118 
1157 void vpImageConvert::convert(const yarp::sig::ImageOf<yarp::sig::PixelRgb> *src, vpImage<vpRGBa> &dest)
1158 {
1159  dest.resize(src->height(), src->width());
1160  for (int i = 0; i < src->height(); i++) {
1161  for (int j = 0; j < src->width(); j++) {
1162  dest[i][j].R = src->pixel(j, i).r;
1163  dest[i][j].G = src->pixel(j, i).g;
1164  dest[i][j].B = src->pixel(j, i).b;
1165  dest[i][j].A = vpRGBa::alpha_default;
1166  }
1167  }
1168 }
1169 
1170 #endif
1171 
1172 #define vpSAT(c) \
1173  if (c & (~255)) { \
1174  if (c < 0) \
1175  c = 0; \
1176  else \
1177  c = 255; \
1178  }
1179 
1187 void vpImageConvert::YUYVToRGBa(unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height)
1188 {
1189  unsigned char *s;
1190  unsigned char *d;
1191  int w, h;
1192  int r, g, b, cr, cg, cb, y1, y2;
1193 
1194  h = (int)height;
1195  w = (int)width;
1196  s = yuyv;
1197  d = rgba;
1198  while (h--) {
1199  int c = w >> 1;
1200  while (c--) {
1201  y1 = *s++;
1202  cb = ((*s - 128) * 454) >> 8;
1203  cg = (*s++ - 128) * 88;
1204  y2 = *s++;
1205  cr = ((*s - 128) * 359) >> 8;
1206  cg = (cg + (*s++ - 128) * 183) >> 8;
1207 
1208  r = y1 + cr;
1209  b = y1 + cb;
1210  g = y1 - cg;
1211  vpSAT(r);
1212  vpSAT(g);
1213  vpSAT(b);
1214 
1215  *d++ = static_cast<unsigned char>(r);
1216  *d++ = static_cast<unsigned char>(g);
1217  *d++ = static_cast<unsigned char>(b);
1218  *d++ = vpRGBa::alpha_default;
1219 
1220  r = y2 + cr;
1221  b = y2 + cb;
1222  g = y2 - cg;
1223  vpSAT(r);
1224  vpSAT(g);
1225  vpSAT(b);
1226 
1227  *d++ = static_cast<unsigned char>(r);
1228  *d++ = static_cast<unsigned char>(g);
1229  *d++ = static_cast<unsigned char>(b);
1230  *d++ = vpRGBa::alpha_default;
1231  }
1232  }
1233 }
1234 
1241 void vpImageConvert::YUYVToRGB(unsigned char *yuyv, unsigned char *rgb, unsigned int width, unsigned int height)
1242 {
1243  unsigned char *s;
1244  unsigned char *d;
1245  int h, w;
1246  int r, g, b, cr, cg, cb, y1, y2;
1247 
1248  h = (int)height;
1249  w = (int)width;
1250  s = yuyv;
1251  d = rgb;
1252  while (h--) {
1253  int c = w >> 1;
1254  while (c--) {
1255  y1 = *s++;
1256  cb = ((*s - 128) * 454) >> 8;
1257  cg = (*s++ - 128) * 88;
1258  y2 = *s++;
1259  cr = ((*s - 128) * 359) >> 8;
1260  cg = (cg + (*s++ - 128) * 183) >> 8;
1261 
1262  r = y1 + cr;
1263  b = y1 + cb;
1264  g = y1 - cg;
1265  vpSAT(r);
1266  vpSAT(g);
1267  vpSAT(b);
1268 
1269  *d++ = static_cast<unsigned char>(r);
1270  *d++ = static_cast<unsigned char>(g);
1271  *d++ = static_cast<unsigned char>(b);
1272 
1273  r = y2 + cr;
1274  b = y2 + cb;
1275  g = y2 - cg;
1276  vpSAT(r);
1277  vpSAT(g);
1278  vpSAT(b);
1279 
1280  *d++ = static_cast<unsigned char>(r);
1281  *d++ = static_cast<unsigned char>(g);
1282  *d++ = static_cast<unsigned char>(b);
1283  }
1284  }
1285 }
1286 
1293 void vpImageConvert::YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
1294 {
1295  unsigned int i = 0, j = 0;
1296 
1297  while (j < size * 2) {
1298  grey[i++] = yuyv[j];
1299  grey[i++] = yuyv[j + 2];
1300  j += 4;
1301  }
1302 }
1303 
1308 void vpImageConvert::YUV411ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
1309 {
1310 #if 1
1311  // std::cout << "call optimized ConvertYUV411ToRGBa()" << std::endl;
1312  for (unsigned int i = size / 4; i; i--) {
1313  int U = (int)((*yuv++ - 128) * 0.354);
1314  int U5 = 5 * U;
1315  int Y0 = *yuv++;
1316  int Y1 = *yuv++;
1317  int V = (int)((*yuv++ - 128) * 0.707);
1318  int V2 = 2 * V;
1319  int Y2 = *yuv++;
1320  int Y3 = *yuv++;
1321  int UV = -U - V;
1322 
1323  // Original equations
1324  // R = Y + 1.402 V
1325  // G = Y - 0.344 U - 0.714 V
1326  // B = Y + 1.772 U
1327  int R = Y0 + V2;
1328  if ((R >> 8) > 0)
1329  R = 255;
1330  else if (R < 0)
1331  R = 0;
1332 
1333  int G = Y0 + UV;
1334  if ((G >> 8) > 0)
1335  G = 255;
1336  else if (G < 0)
1337  G = 0;
1338 
1339  int B = Y0 + U5;
1340  if ((B >> 8) > 0)
1341  B = 255;
1342  else if (B < 0)
1343  B = 0;
1344 
1345  *rgba++ = (unsigned char)R;
1346  *rgba++ = (unsigned char)G;
1347  *rgba++ = (unsigned char)B;
1348  *rgba++ = vpRGBa::alpha_default;
1349 
1350  //---
1351  R = Y1 + V2;
1352  if ((R >> 8) > 0)
1353  R = 255;
1354  else if (R < 0)
1355  R = 0;
1356 
1357  G = Y1 + UV;
1358  if ((G >> 8) > 0)
1359  G = 255;
1360  else if (G < 0)
1361  G = 0;
1362 
1363  B = Y1 + U5;
1364  if ((B >> 8) > 0)
1365  B = 255;
1366  else if (B < 0)
1367  B = 0;
1368 
1369  *rgba++ = (unsigned char)R;
1370  *rgba++ = (unsigned char)G;
1371  *rgba++ = (unsigned char)B;
1372  *rgba++ = vpRGBa::alpha_default;
1373 
1374  //---
1375  R = Y2 + V2;
1376  if ((R >> 8) > 0)
1377  R = 255;
1378  else if (R < 0)
1379  R = 0;
1380 
1381  G = Y2 + UV;
1382  if ((G >> 8) > 0)
1383  G = 255;
1384  else if (G < 0)
1385  G = 0;
1386 
1387  B = Y2 + U5;
1388  if ((B >> 8) > 0)
1389  B = 255;
1390  else if (B < 0)
1391  B = 0;
1392 
1393  *rgba++ = (unsigned char)R;
1394  *rgba++ = (unsigned char)G;
1395  *rgba++ = (unsigned char)B;
1396  *rgba++ = vpRGBa::alpha_default;
1397 
1398  //---
1399  R = Y3 + V2;
1400  if ((R >> 8) > 0)
1401  R = 255;
1402  else if (R < 0)
1403  R = 0;
1404 
1405  G = Y3 + UV;
1406  if ((G >> 8) > 0)
1407  G = 255;
1408  else if (G < 0)
1409  G = 0;
1410 
1411  B = Y3 + U5;
1412  if ((B >> 8) > 0)
1413  B = 255;
1414  else if (B < 0)
1415  B = 0;
1416 
1417  *rgba++ = (unsigned char)R;
1418  *rgba++ = (unsigned char)G;
1419  *rgba++ = (unsigned char)B;
1420  *rgba++ = vpRGBa::alpha_default;
1421  }
1422 #else
1423  // tres tres lent ....
1424  unsigned int i = 0, j = 0;
1425  unsigned char r, g, b;
1426  while (j < numpixels * 3 / 2) {
1427 
1428  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 3], r, g, b);
1429  rgba[i] = r;
1430  rgba[i + 1] = g;
1431  rgba[i + 2] = b;
1432  rgba[i + 3] = vpRGBa::alpha_default;
1433  i += 4;
1434 
1435  YUVToRGB(yuv[j + 2], yuv[j], yuv[j + 3], r, g, b);
1436  rgba[i] = r;
1437  rgba[i + 1] = g;
1438  rgba[i + 2] = b;
1439  rgba[i + 3] = vpRGBa::alpha_default;
1440  i += 4;
1441 
1442  YUVToRGB(yuv[j + 4], yuv[j], yuv[j + 3], r, g, b);
1443  rgba[i] = r;
1444  rgba[i + 1] = g;
1445  rgba[i + 2] = b;
1446  rgba[i + 3] = vpRGBa::alpha_default;
1447  i += 4;
1448 
1449  YUVToRGB(yuv[j + 5], yuv[j], yuv[j + 3], r, g, b);
1450  rgba[i] = r;
1451  rgba[i + 1] = g;
1452  rgba[i + 2] = b;
1453  rgba[i + 3] = vpRGBa::alpha_default;
1454  i += 4;
1455 
1456  j += 6;
1457  }
1458 #endif
1459 }
1460 
1469 void vpImageConvert::YUV422ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
1470 {
1471 
1472 #if 1
1473  // std::cout << "call optimized convertYUV422ToRGBa()" << std::endl;
1474  for (unsigned int i = size / 2; i; i--) {
1475  int U = (int)((*yuv++ - 128) * 0.354);
1476  int U5 = 5 * U;
1477  int Y0 = *yuv++;
1478  int V = (int)((*yuv++ - 128) * 0.707);
1479  int V2 = 2 * V;
1480  int Y1 = *yuv++;
1481  int UV = -U - V;
1482 
1483  //---
1484  int R = Y0 + V2;
1485  if ((R >> 8) > 0)
1486  R = 255;
1487  else if (R < 0)
1488  R = 0;
1489 
1490  int G = Y0 + UV;
1491  if ((G >> 8) > 0)
1492  G = 255;
1493  else if (G < 0)
1494  G = 0;
1495 
1496  int B = Y0 + U5;
1497  if ((B >> 8) > 0)
1498  B = 255;
1499  else if (B < 0)
1500  B = 0;
1501 
1502  *rgba++ = (unsigned char)R;
1503  *rgba++ = (unsigned char)G;
1504  *rgba++ = (unsigned char)B;
1505  *rgba++ = vpRGBa::alpha_default;
1506 
1507  //---
1508  R = Y1 + V2;
1509  if ((R >> 8) > 0)
1510  R = 255;
1511  else if (R < 0)
1512  R = 0;
1513 
1514  G = Y1 + UV;
1515  if ((G >> 8) > 0)
1516  G = 255;
1517  else if (G < 0)
1518  G = 0;
1519 
1520  B = Y1 + U5;
1521  if ((B >> 8) > 0)
1522  B = 255;
1523  else if (B < 0)
1524  B = 0;
1525 
1526  *rgba++ = (unsigned char)R;
1527  *rgba++ = (unsigned char)G;
1528  *rgba++ = (unsigned char)B;
1529  *rgba++ = vpRGBa::alpha_default;
1530  }
1531 
1532 #else
1533  // tres tres lent ....
1534  unsigned int i = 0, j = 0;
1535  unsigned char r, g, b;
1536 
1537  while (j < size * 2) {
1538 
1539  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 2], r, g, b);
1540  rgba[i] = r;
1541  rgba[i + 1] = g;
1542  rgba[i + 2] = b;
1543  rgba[i + 3] = vpRGBa::alpha_default;
1544  i += 4;
1545 
1546  YUVToRGB(yuv[j + 3], yuv[j], yuv[j + 2], r, g, b);
1547  rgba[i] = r;
1548  rgba[i + 1] = g;
1549  rgba[i + 2] = b;
1550  rgba[i + 3] = vpRGBa::alpha_default;
1551  i += 4;
1552  j += 4;
1553  }
1554 #endif
1555 }
1556 
1561 void vpImageConvert::YUV411ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
1562 {
1563  unsigned int i = 0, j = 0;
1564  while (j < size * 3 / 2) {
1565  grey[i] = yuv[j + 1];
1566  grey[i + 1] = yuv[j + 2];
1567  grey[i + 2] = yuv[j + 4];
1568  grey[i + 3] = yuv[j + 5];
1569 
1570  i += 4;
1571 
1572  j += 6;
1573  }
1574 }
1575 
1582 void vpImageConvert::YUV422ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
1583 {
1584 #if 1
1585  // std::cout << "call optimized convertYUV422ToRGB()" << std::endl;
1586  for (unsigned int i = size / 2; i; i--) {
1587  int U = (int)((*yuv++ - 128) * 0.354);
1588  int U5 = 5 * U;
1589  int Y0 = *yuv++;
1590  int V = (int)((*yuv++ - 128) * 0.707);
1591  int V2 = 2 * V;
1592  int Y1 = *yuv++;
1593  int UV = -U - V;
1594 
1595  //---
1596  int R = Y0 + V2;
1597  if ((R >> 8) > 0)
1598  R = 255;
1599  else if (R < 0)
1600  R = 0;
1601 
1602  int G = Y0 + UV;
1603  if ((G >> 8) > 0)
1604  G = 255;
1605  else if (G < 0)
1606  G = 0;
1607 
1608  int B = Y0 + U5;
1609  if ((B >> 8) > 0)
1610  B = 255;
1611  else if (B < 0)
1612  B = 0;
1613 
1614  *rgb++ = (unsigned char)R;
1615  *rgb++ = (unsigned char)G;
1616  *rgb++ = (unsigned char)B;
1617 
1618  //---
1619  R = Y1 + V2;
1620  if ((R >> 8) > 0)
1621  R = 255;
1622  else if (R < 0)
1623  R = 0;
1624 
1625  G = Y1 + UV;
1626  if ((G >> 8) > 0)
1627  G = 255;
1628  else if (G < 0)
1629  G = 0;
1630 
1631  B = Y1 + U5;
1632  if ((B >> 8) > 0)
1633  B = 255;
1634  else if (B < 0)
1635  B = 0;
1636 
1637  *rgb++ = (unsigned char)R;
1638  *rgb++ = (unsigned char)G;
1639  *rgb++ = (unsigned char)B;
1640  }
1641 
1642 #else
1643  // tres tres lent ....
1644  unsigned int i = 0, j = 0;
1645  unsigned char r, g, b;
1646 
1647  while (j < size * 2) {
1648 
1649  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 2], r, g, b);
1650  rgb[i] = r;
1651  rgb[i + 1] = g;
1652  rgb[i + 2] = b;
1653  i += 3;
1654 
1655  YUVToRGB(yuv[j + 3], yuv[j], yuv[j + 2], r, g, b);
1656  rgb[i] = r;
1657  rgb[i + 1] = g;
1658  rgb[i + 2] = b;
1659  i += 3;
1660  j += 4;
1661  }
1662 #endif
1663 }
1664 
1671 void vpImageConvert::YUV422ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
1672 {
1673  unsigned int i = 0, j = 0;
1674 
1675  while (j < size * 2) {
1676  grey[i++] = yuv[j + 1];
1677  grey[i++] = yuv[j + 3];
1678  j += 4;
1679  }
1680 }
1681 
1686 void vpImageConvert::YUV411ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
1687 {
1688 #if 1
1689  // std::cout << "call optimized ConvertYUV411ToRGB()" << std::endl;
1690  for (unsigned int i = size / 4; i; i--) {
1691  int U = (int)((*yuv++ - 128) * 0.354);
1692  int U5 = 5 * U;
1693  int Y0 = *yuv++;
1694  int Y1 = *yuv++;
1695  int V = (int)((*yuv++ - 128) * 0.707);
1696  int V2 = 2 * V;
1697  int Y2 = *yuv++;
1698  int Y3 = *yuv++;
1699  int UV = -U - V;
1700 
1701  // Original equations
1702  // R = Y + 1.402 V
1703  // G = Y - 0.344 U - 0.714 V
1704  // B = Y + 1.772 U
1705  int R = Y0 + V2;
1706  if ((R >> 8) > 0)
1707  R = 255;
1708  else if (R < 0)
1709  R = 0;
1710 
1711  int G = Y0 + UV;
1712  if ((G >> 8) > 0)
1713  G = 255;
1714  else if (G < 0)
1715  G = 0;
1716 
1717  int B = Y0 + U5;
1718  if ((B >> 8) > 0)
1719  B = 255;
1720  else if (B < 0)
1721  B = 0;
1722 
1723  *rgb++ = (unsigned char)R;
1724  *rgb++ = (unsigned char)G;
1725  *rgb++ = (unsigned char)B;
1726 
1727  //---
1728  R = Y1 + V2;
1729  if ((R >> 8) > 0)
1730  R = 255;
1731  else if (R < 0)
1732  R = 0;
1733 
1734  G = Y1 + UV;
1735  if ((G >> 8) > 0)
1736  G = 255;
1737  else if (G < 0)
1738  G = 0;
1739 
1740  B = Y1 + U5;
1741  if ((B >> 8) > 0)
1742  B = 255;
1743  else if (B < 0)
1744  B = 0;
1745 
1746  *rgb++ = (unsigned char)R;
1747  *rgb++ = (unsigned char)G;
1748  *rgb++ = (unsigned char)B;
1749 
1750  //---
1751  R = Y2 + V2;
1752  if ((R >> 8) > 0)
1753  R = 255;
1754  else if (R < 0)
1755  R = 0;
1756 
1757  G = Y2 + UV;
1758  if ((G >> 8) > 0)
1759  G = 255;
1760  else if (G < 0)
1761  G = 0;
1762 
1763  B = Y2 + U5;
1764  if ((B >> 8) > 0)
1765  B = 255;
1766  else if (B < 0)
1767  B = 0;
1768 
1769  *rgb++ = (unsigned char)R;
1770  *rgb++ = (unsigned char)G;
1771  *rgb++ = (unsigned char)B;
1772 
1773  //---
1774  R = Y3 + V2;
1775  if ((R >> 8) > 0)
1776  R = 255;
1777  else if (R < 0)
1778  R = 0;
1779 
1780  G = Y3 + UV;
1781  if ((G >> 8) > 0)
1782  G = 255;
1783  else if (G < 0)
1784  G = 0;
1785 
1786  B = Y3 + U5;
1787  if ((B >> 8) > 0)
1788  B = 255;
1789  else if (B < 0)
1790  B = 0;
1791 
1792  *rgb++ = (unsigned char)R;
1793  *rgb++ = (unsigned char)G;
1794  *rgb++ = (unsigned char)B;
1795  }
1796 #else
1797  // tres tres lent ....
1798 
1799  unsigned int i = 0, j = 0;
1800  unsigned char r, g, b;
1801 
1802  while (j < size * 3 / 2) {
1803  YUVToRGB(yuv[j + 1], yuv[j], yuv[j + 3], r, g, b);
1804  rgb[i] = r;
1805  rgb[i + 1] = g;
1806  rgb[i + 2] = b;
1807  i += 3;
1808 
1809  YUVToRGB(yuv[j + 2], yuv[j], yuv[j + 3], r, g, b);
1810  rgb[i] = r;
1811  rgb[i + 1] = g;
1812  rgb[i + 2] = b;
1813  i += 3;
1814 
1815  YUVToRGB(yuv[j + 4], yuv[j], yuv[j + 3], r, g, b);
1816  rgb[i] = r;
1817  rgb[i + 1] = g;
1818  rgb[i + 2] = b;
1819  i += 3;
1820 
1821  YUVToRGB(yuv[j + 5], yuv[j], yuv[j + 3], r, g, b);
1822  rgb[i] = r;
1823  rgb[i + 1] = g;
1824  rgb[i + 2] = b;
1825  i += 3;
1826  // TRACE("r= %d g=%d b=%d", r, g, b);
1827 
1828  j += 6;
1829  }
1830 #endif
1831 }
1832 
1838 void vpImageConvert::YUV420ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
1839 {
1840  // std::cout << "call optimized ConvertYUV420ToRGBa()" << std::endl;
1841  int U, V, R, G, B, V2, U5, UV;
1842  int Y0, Y1, Y2, Y3;
1843  unsigned int size = width * height;
1844  unsigned char *iU = yuv + size;
1845  unsigned char *iV = yuv + 5 * size / 4;
1846  for (unsigned int i = 0; i < height / 2; i++) {
1847  for (unsigned int j = 0; j < width / 2; j++) {
1848  U = (int)((*iU++ - 128) * 0.354);
1849  U5 = 5 * U;
1850  V = (int)((*iV++ - 128) * 0.707);
1851  V2 = 2 * V;
1852  UV = -U - V;
1853  Y0 = *yuv++;
1854  Y1 = *yuv;
1855  yuv = yuv + width - 1;
1856  Y2 = *yuv++;
1857  Y3 = *yuv;
1858  yuv = yuv - width + 1;
1859 
1860  // Original equations
1861  // R = Y + 1.402 V
1862  // G = Y - 0.344 U - 0.714 V
1863  // B = Y + 1.772 U
1864  R = Y0 + V2;
1865  if ((R >> 8) > 0)
1866  R = 255;
1867  else if (R < 0)
1868  R = 0;
1869 
1870  G = Y0 + UV;
1871  if ((G >> 8) > 0)
1872  G = 255;
1873  else if (G < 0)
1874  G = 0;
1875 
1876  B = Y0 + U5;
1877  if ((B >> 8) > 0)
1878  B = 255;
1879  else if (B < 0)
1880  B = 0;
1881 
1882  *rgba++ = (unsigned char)R;
1883  *rgba++ = (unsigned char)G;
1884  *rgba++ = (unsigned char)B;
1885  *rgba++ = vpRGBa::alpha_default;
1886 
1887  //---
1888  R = Y1 + V2;
1889  if ((R >> 8) > 0)
1890  R = 255;
1891  else if (R < 0)
1892  R = 0;
1893 
1894  G = Y1 + UV;
1895  if ((G >> 8) > 0)
1896  G = 255;
1897  else if (G < 0)
1898  G = 0;
1899 
1900  B = Y1 + U5;
1901  if ((B >> 8) > 0)
1902  B = 255;
1903  else if (B < 0)
1904  B = 0;
1905 
1906  *rgba++ = (unsigned char)R;
1907  *rgba++ = (unsigned char)G;
1908  *rgba++ = (unsigned char)B;
1909  *rgba = vpRGBa::alpha_default;
1910  rgba = rgba + 4 * width - 7;
1911 
1912  //---
1913  R = Y2 + V2;
1914  if ((R >> 8) > 0)
1915  R = 255;
1916  else if (R < 0)
1917  R = 0;
1918 
1919  G = Y2 + UV;
1920  if ((G >> 8) > 0)
1921  G = 255;
1922  else if (G < 0)
1923  G = 0;
1924 
1925  B = Y2 + U5;
1926  if ((B >> 8) > 0)
1927  B = 255;
1928  else if (B < 0)
1929  B = 0;
1930 
1931  *rgba++ = (unsigned char)R;
1932  *rgba++ = (unsigned char)G;
1933  *rgba++ = (unsigned char)B;
1934  *rgba++ = vpRGBa::alpha_default;
1935 
1936  //---
1937  R = Y3 + V2;
1938  if ((R >> 8) > 0)
1939  R = 255;
1940  else if (R < 0)
1941  R = 0;
1942 
1943  G = Y3 + UV;
1944  if ((G >> 8) > 0)
1945  G = 255;
1946  else if (G < 0)
1947  G = 0;
1948 
1949  B = Y3 + U5;
1950  if ((B >> 8) > 0)
1951  B = 255;
1952  else if (B < 0)
1953  B = 0;
1954 
1955  *rgba++ = (unsigned char)R;
1956  *rgba++ = (unsigned char)G;
1957  *rgba++ = (unsigned char)B;
1958  *rgba = vpRGBa::alpha_default;
1959  rgba = rgba - 4 * width + 1;
1960  }
1961  yuv += width;
1962  rgba += 4 * width;
1963  }
1964 }
1965 
1969 void vpImageConvert::YUV420ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
1970 {
1971  // std::cout << "call optimized ConvertYUV420ToRGB()" << std::endl;
1972  int U, V, R, G, B, V2, U5, UV;
1973  int Y0, Y1, Y2, Y3;
1974  unsigned int size = width * height;
1975  unsigned char *iU = yuv + size;
1976  unsigned char *iV = yuv + 5 * size / 4;
1977  for (unsigned int i = 0; i < height / 2; i++) {
1978  for (unsigned int j = 0; j < width / 2; j++) {
1979  U = (int)((*iU++ - 128) * 0.354);
1980  U5 = 5 * U;
1981  V = (int)((*iV++ - 128) * 0.707);
1982  V2 = 2 * V;
1983  UV = -U - V;
1984  Y0 = *yuv++;
1985  Y1 = *yuv;
1986  yuv = yuv + width - 1;
1987  Y2 = *yuv++;
1988  Y3 = *yuv;
1989  yuv = yuv - width + 1;
1990 
1991  // Original equations
1992  // R = Y + 1.402 V
1993  // G = Y - 0.344 U - 0.714 V
1994  // B = Y + 1.772 U
1995  R = Y0 + V2;
1996  if ((R >> 8) > 0)
1997  R = 255;
1998  else if (R < 0)
1999  R = 0;
2000 
2001  G = Y0 + UV;
2002  if ((G >> 8) > 0)
2003  G = 255;
2004  else if (G < 0)
2005  G = 0;
2006 
2007  B = Y0 + U5;
2008  if ((B >> 8) > 0)
2009  B = 255;
2010  else if (B < 0)
2011  B = 0;
2012 
2013  *rgb++ = (unsigned char)R;
2014  *rgb++ = (unsigned char)G;
2015  *rgb++ = (unsigned char)B;
2016 
2017  //---
2018  R = Y1 + V2;
2019  if ((R >> 8) > 0)
2020  R = 255;
2021  else if (R < 0)
2022  R = 0;
2023 
2024  G = Y1 + UV;
2025  if ((G >> 8) > 0)
2026  G = 255;
2027  else if (G < 0)
2028  G = 0;
2029 
2030  B = Y1 + U5;
2031  if ((B >> 8) > 0)
2032  B = 255;
2033  else if (B < 0)
2034  B = 0;
2035 
2036  *rgb++ = (unsigned char)R;
2037  *rgb++ = (unsigned char)G;
2038  *rgb = (unsigned char)B;
2039  rgb = rgb + 3 * width - 5;
2040 
2041  //---
2042  R = Y2 + V2;
2043  if ((R >> 8) > 0)
2044  R = 255;
2045  else if (R < 0)
2046  R = 0;
2047 
2048  G = Y2 + UV;
2049  if ((G >> 8) > 0)
2050  G = 255;
2051  else if (G < 0)
2052  G = 0;
2053 
2054  B = Y2 + U5;
2055  if ((B >> 8) > 0)
2056  B = 255;
2057  else if (B < 0)
2058  B = 0;
2059 
2060  *rgb++ = (unsigned char)R;
2061  *rgb++ = (unsigned char)G;
2062  *rgb++ = (unsigned char)B;
2063 
2064  //---
2065  R = Y3 + V2;
2066  if ((R >> 8) > 0)
2067  R = 255;
2068  else if (R < 0)
2069  R = 0;
2070 
2071  G = Y3 + UV;
2072  if ((G >> 8) > 0)
2073  G = 255;
2074  else if (G < 0)
2075  G = 0;
2076 
2077  B = Y3 + U5;
2078  if ((B >> 8) > 0)
2079  B = 255;
2080  else if (B < 0)
2081  B = 0;
2082 
2083  *rgb++ = (unsigned char)R;
2084  *rgb++ = (unsigned char)G;
2085  *rgb = (unsigned char)B;
2086  rgb = rgb - 3 * width + 1;
2087  }
2088  yuv += width;
2089  rgb += 3 * width;
2090  }
2091 }
2092 
2096 void vpImageConvert::YUV420ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
2097 {
2098  for (unsigned int i = 0; i < size; i++) {
2099  *grey++ = *yuv++;
2100  }
2101 }
2102 
2108 void vpImageConvert::YUV444ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
2109 {
2110  for (unsigned int i = 0; i < size; i++) {
2111  int U = (int)((*yuv++ - 128) * 0.354);
2112  int U5 = 5 * U;
2113  int Y = *yuv++;
2114  int V = (int)((*yuv++ - 128) * 0.707);
2115  int V2 = 2 * V;
2116  int UV = -U - V;
2117 
2118  // Original equations
2119  // R = Y + 1.402 V
2120  // G = Y - 0.344 U - 0.714 V
2121  // B = Y + 1.772 U
2122  int R = Y + V2;
2123  if ((R >> 8) > 0)
2124  R = 255;
2125  else if (R < 0)
2126  R = 0;
2127 
2128  int G = Y + UV;
2129  if ((G >> 8) > 0)
2130  G = 255;
2131  else if (G < 0)
2132  G = 0;
2133 
2134  int B = Y + U5;
2135  if ((B >> 8) > 0)
2136  B = 255;
2137  else if (B < 0)
2138  B = 0;
2139 
2140  *rgba++ = (unsigned char)R;
2141  *rgba++ = (unsigned char)G;
2142  *rgba++ = (unsigned char)B;
2143  *rgba++ = vpRGBa::alpha_default;
2144  }
2145 }
2146 
2150 void vpImageConvert::YUV444ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
2151 {
2152  for (unsigned int i = 0; i < size; i++) {
2153  int U = (int)((*yuv++ - 128) * 0.354);
2154  int U5 = 5 * U;
2155  int Y = *yuv++;
2156  int V = (int)((*yuv++ - 128) * 0.707);
2157  int V2 = 2 * V;
2158  int UV = -U - V;
2159 
2160  // Original equations
2161  // R = Y + 1.402 V
2162  // G = Y - 0.344 U - 0.714 V
2163  // B = Y + 1.772 U
2164  int R = Y + V2;
2165  if ((R >> 8) > 0)
2166  R = 255;
2167  else if (R < 0)
2168  R = 0;
2169 
2170  int G = Y + UV;
2171  if ((G >> 8) > 0)
2172  G = 255;
2173  else if (G < 0)
2174  G = 0;
2175 
2176  int B = Y + U5;
2177  if ((B >> 8) > 0)
2178  B = 255;
2179  else if (B < 0)
2180  B = 0;
2181 
2182  *rgb++ = (unsigned char)R;
2183  *rgb++ = (unsigned char)G;
2184  *rgb++ = (unsigned char)B;
2185  }
2186 }
2187 
2191 void vpImageConvert::YUV444ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
2192 {
2193  yuv++;
2194  for (unsigned int i = 0; i < size; i++) {
2195  *grey++ = *yuv;
2196  yuv = yuv + 3;
2197  }
2198 }
2199 
2205 void vpImageConvert::YV12ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
2206 {
2207  // std::cout << "call optimized ConvertYV12ToRGBa()" << std::endl;
2208  int U, V, R, G, B, V2, U5, UV;
2209  int Y0, Y1, Y2, Y3;
2210  unsigned int size = width * height;
2211  unsigned char *iV = yuv + size;
2212  unsigned char *iU = yuv + 5 * size / 4;
2213  for (unsigned int i = 0; i < height / 2; i++) {
2214  for (unsigned int j = 0; j < width / 2; j++) {
2215  U = (int)((*iU++ - 128) * 0.354);
2216  U5 = 5 * U;
2217  V = (int)((*iV++ - 128) * 0.707);
2218  V2 = 2 * V;
2219  UV = -U - V;
2220  Y0 = *yuv++;
2221  Y1 = *yuv;
2222  yuv = yuv + width - 1;
2223  Y2 = *yuv++;
2224  Y3 = *yuv;
2225  yuv = yuv - width + 1;
2226 
2227  // Original equations
2228  // R = Y + 1.402 V
2229  // G = Y - 0.344 U - 0.714 V
2230  // B = Y + 1.772 U
2231  R = Y0 + V2;
2232  if ((R >> 8) > 0)
2233  R = 255;
2234  else if (R < 0)
2235  R = 0;
2236 
2237  G = Y0 + UV;
2238  if ((G >> 8) > 0)
2239  G = 255;
2240  else if (G < 0)
2241  G = 0;
2242 
2243  B = Y0 + U5;
2244  if ((B >> 8) > 0)
2245  B = 255;
2246  else if (B < 0)
2247  B = 0;
2248 
2249  *rgba++ = (unsigned char)R;
2250  *rgba++ = (unsigned char)G;
2251  *rgba++ = (unsigned char)B;
2252  *rgba++ = vpRGBa::alpha_default;
2253 
2254  //---
2255  R = Y1 + V2;
2256  if ((R >> 8) > 0)
2257  R = 255;
2258  else if (R < 0)
2259  R = 0;
2260 
2261  G = Y1 + UV;
2262  if ((G >> 8) > 0)
2263  G = 255;
2264  else if (G < 0)
2265  G = 0;
2266 
2267  B = Y1 + U5;
2268  if ((B >> 8) > 0)
2269  B = 255;
2270  else if (B < 0)
2271  B = 0;
2272 
2273  *rgba++ = (unsigned char)R;
2274  *rgba++ = (unsigned char)G;
2275  *rgba++ = (unsigned char)B;
2276  *rgba = 0;
2277  rgba = rgba + 4 * width - 7;
2278 
2279  //---
2280  R = Y2 + V2;
2281  if ((R >> 8) > 0)
2282  R = 255;
2283  else if (R < 0)
2284  R = 0;
2285 
2286  G = Y2 + UV;
2287  if ((G >> 8) > 0)
2288  G = 255;
2289  else if (G < 0)
2290  G = 0;
2291 
2292  B = Y2 + U5;
2293  if ((B >> 8) > 0)
2294  B = 255;
2295  else if (B < 0)
2296  B = 0;
2297 
2298  *rgba++ = (unsigned char)R;
2299  *rgba++ = (unsigned char)G;
2300  *rgba++ = (unsigned char)B;
2301  *rgba++ = vpRGBa::alpha_default;
2302 
2303  //---
2304  R = Y3 + V2;
2305  if ((R >> 8) > 0)
2306  R = 255;
2307  else if (R < 0)
2308  R = 0;
2309 
2310  G = Y3 + UV;
2311  if ((G >> 8) > 0)
2312  G = 255;
2313  else if (G < 0)
2314  G = 0;
2315 
2316  B = Y3 + U5;
2317  if ((B >> 8) > 0)
2318  B = 255;
2319  else if (B < 0)
2320  B = 0;
2321 
2322  *rgba++ = (unsigned char)R;
2323  *rgba++ = (unsigned char)G;
2324  *rgba++ = (unsigned char)B;
2325  *rgba = vpRGBa::alpha_default;
2326  rgba = rgba - 4 * width + 1;
2327  }
2328  yuv += width;
2329  rgba += 4 * width;
2330  }
2331 }
2332 
2336 void vpImageConvert::YV12ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int height, unsigned int width)
2337 {
2338  // std::cout << "call optimized ConvertYV12ToRGB()" << std::endl;
2339  int U, V, R, G, B, V2, U5, UV;
2340  int Y0, Y1, Y2, Y3;
2341  unsigned int size = width * height;
2342  unsigned char *iV = yuv + size;
2343  unsigned char *iU = yuv + 5 * size / 4;
2344  for (unsigned int i = 0; i < height / 2; i++) {
2345  for (unsigned int j = 0; j < width / 2; j++) {
2346  U = (int)((*iU++ - 128) * 0.354);
2347  U5 = 5 * U;
2348  V = (int)((*iV++ - 128) * 0.707);
2349  V2 = 2 * V;
2350  UV = -U - V;
2351  Y0 = *yuv++;
2352  Y1 = *yuv;
2353  yuv = yuv + width - 1;
2354  Y2 = *yuv++;
2355  Y3 = *yuv;
2356  yuv = yuv - width + 1;
2357 
2358  // Original equations
2359  // R = Y + 1.402 V
2360  // G = Y - 0.344 U - 0.714 V
2361  // B = Y + 1.772 U
2362  R = Y0 + V2;
2363  if ((R >> 8) > 0)
2364  R = 255;
2365  else if (R < 0)
2366  R = 0;
2367 
2368  G = Y0 + UV;
2369  if ((G >> 8) > 0)
2370  G = 255;
2371  else if (G < 0)
2372  G = 0;
2373 
2374  B = Y0 + U5;
2375  if ((B >> 8) > 0)
2376  B = 255;
2377  else if (B < 0)
2378  B = 0;
2379 
2380  *rgb++ = (unsigned char)R;
2381  *rgb++ = (unsigned char)G;
2382  *rgb++ = (unsigned char)B;
2383 
2384  //---
2385  R = Y1 + V2;
2386  if ((R >> 8) > 0)
2387  R = 255;
2388  else if (R < 0)
2389  R = 0;
2390 
2391  G = Y1 + UV;
2392  if ((G >> 8) > 0)
2393  G = 255;
2394  else if (G < 0)
2395  G = 0;
2396 
2397  B = Y1 + U5;
2398  if ((B >> 8) > 0)
2399  B = 255;
2400  else if (B < 0)
2401  B = 0;
2402 
2403  *rgb++ = (unsigned char)R;
2404  *rgb++ = (unsigned char)G;
2405  *rgb = (unsigned char)B;
2406  rgb = rgb + 3 * width - 5;
2407 
2408  //---
2409  R = Y2 + V2;
2410  if ((R >> 8) > 0)
2411  R = 255;
2412  else if (R < 0)
2413  R = 0;
2414 
2415  G = Y2 + UV;
2416  if ((G >> 8) > 0)
2417  G = 255;
2418  else if (G < 0)
2419  G = 0;
2420 
2421  B = Y2 + U5;
2422  if ((B >> 8) > 0)
2423  B = 255;
2424  else if (B < 0)
2425  B = 0;
2426 
2427  *rgb++ = (unsigned char)R;
2428  *rgb++ = (unsigned char)G;
2429  *rgb++ = (unsigned char)B;
2430 
2431  //---
2432  R = Y3 + V2;
2433  if ((R >> 8) > 0)
2434  R = 255;
2435  else if (R < 0)
2436  R = 0;
2437 
2438  G = Y3 + UV;
2439  if ((G >> 8) > 0)
2440  G = 255;
2441  else if (G < 0)
2442  G = 0;
2443 
2444  B = Y3 + U5;
2445  if ((B >> 8) > 0)
2446  B = 255;
2447  else if (B < 0)
2448  B = 0;
2449 
2450  *rgb++ = (unsigned char)R;
2451  *rgb++ = (unsigned char)G;
2452  *rgb = (unsigned char)B;
2453  rgb = rgb - 3 * width + 1;
2454  }
2455  yuv += width;
2456  rgb += 3 * width;
2457  }
2458 }
2459 
2465 void vpImageConvert::YVU9ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
2466 {
2467  // std::cout << "call optimized ConvertYVU9ToRGBa()" << std::endl;
2468  int U, V, R, G, B, V2, U5, UV;
2469  int Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9, Y10, Y11, Y12, Y13, Y14, Y15;
2470  unsigned int size = width * height;
2471  unsigned char *iV = yuv + size;
2472  unsigned char *iU = yuv + 17 * size / 16;
2473  for (unsigned int i = 0; i < height / 4; i++) {
2474  for (unsigned int j = 0; j < width / 4; j++) {
2475  U = (int)((*iU++ - 128) * 0.354);
2476  U5 = 5 * U;
2477  V = (int)((*iV++ - 128) * 0.707);
2478  V2 = 2 * V;
2479  UV = -U - V;
2480  Y0 = *yuv++;
2481  Y1 = *yuv++;
2482  Y2 = *yuv++;
2483  Y3 = *yuv;
2484  yuv = yuv + width - 3;
2485  Y4 = *yuv++;
2486  Y5 = *yuv++;
2487  Y6 = *yuv++;
2488  Y7 = *yuv;
2489  yuv = yuv + width - 3;
2490  Y8 = *yuv++;
2491  Y9 = *yuv++;
2492  Y10 = *yuv++;
2493  Y11 = *yuv;
2494  yuv = yuv + width - 3;
2495  Y12 = *yuv++;
2496  Y13 = *yuv++;
2497  Y14 = *yuv++;
2498  Y15 = *yuv;
2499  yuv = yuv - 3 * width + 1;
2500 
2501  // Original equations
2502  // R = Y + 1.402 V
2503  // G = Y - 0.344 U - 0.714 V
2504  // B = Y + 1.772 U
2505  R = Y0 + V2;
2506  if ((R >> 8) > 0)
2507  R = 255;
2508  else if (R < 0)
2509  R = 0;
2510 
2511  G = Y0 + UV;
2512  if ((G >> 8) > 0)
2513  G = 255;
2514  else if (G < 0)
2515  G = 0;
2516 
2517  B = Y0 + U5;
2518  if ((B >> 8) > 0)
2519  B = 255;
2520  else if (B < 0)
2521  B = 0;
2522 
2523  *rgba++ = (unsigned char)R;
2524  *rgba++ = (unsigned char)G;
2525  *rgba++ = (unsigned char)B;
2526  *rgba++ = vpRGBa::alpha_default;
2527 
2528  //---
2529  R = Y1 + V2;
2530  if ((R >> 8) > 0)
2531  R = 255;
2532  else if (R < 0)
2533  R = 0;
2534 
2535  G = Y1 + UV;
2536  if ((G >> 8) > 0)
2537  G = 255;
2538  else if (G < 0)
2539  G = 0;
2540 
2541  B = Y1 + U5;
2542  if ((B >> 8) > 0)
2543  B = 255;
2544  else if (B < 0)
2545  B = 0;
2546 
2547  *rgba++ = (unsigned char)R;
2548  *rgba++ = (unsigned char)G;
2549  *rgba++ = (unsigned char)B;
2550  *rgba++ = vpRGBa::alpha_default;
2551 
2552  //---
2553  R = Y2 + V2;
2554  if ((R >> 8) > 0)
2555  R = 255;
2556  else if (R < 0)
2557  R = 0;
2558 
2559  G = Y2 + UV;
2560  if ((G >> 8) > 0)
2561  G = 255;
2562  else if (G < 0)
2563  G = 0;
2564 
2565  B = Y2 + U5;
2566  if ((B >> 8) > 0)
2567  B = 255;
2568  else if (B < 0)
2569  B = 0;
2570 
2571  *rgba++ = (unsigned char)R;
2572  *rgba++ = (unsigned char)G;
2573  *rgba++ = (unsigned char)B;
2574  *rgba++ = vpRGBa::alpha_default;
2575 
2576  //---
2577  R = Y3 + V2;
2578  if ((R >> 8) > 0)
2579  R = 255;
2580  else if (R < 0)
2581  R = 0;
2582 
2583  G = Y3 + UV;
2584  if ((G >> 8) > 0)
2585  G = 255;
2586  else if (G < 0)
2587  G = 0;
2588 
2589  B = Y3 + U5;
2590  if ((B >> 8) > 0)
2591  B = 255;
2592  else if (B < 0)
2593  B = 0;
2594 
2595  *rgba++ = (unsigned char)R;
2596  *rgba++ = (unsigned char)G;
2597  *rgba++ = (unsigned char)B;
2598  *rgba = vpRGBa::alpha_default;
2599  rgba = rgba + 4 * width - 15;
2600 
2601  R = Y4 + V2;
2602  if ((R >> 8) > 0)
2603  R = 255;
2604  else if (R < 0)
2605  R = 0;
2606 
2607  G = Y4 + UV;
2608  if ((G >> 8) > 0)
2609  G = 255;
2610  else if (G < 0)
2611  G = 0;
2612 
2613  B = Y4 + U5;
2614  if ((B >> 8) > 0)
2615  B = 255;
2616  else if (B < 0)
2617  B = 0;
2618 
2619  *rgba++ = (unsigned char)R;
2620  *rgba++ = (unsigned char)G;
2621  *rgba++ = (unsigned char)B;
2622  *rgba++ = vpRGBa::alpha_default;
2623 
2624  //---
2625  R = Y5 + V2;
2626  if ((R >> 8) > 0)
2627  R = 255;
2628  else if (R < 0)
2629  R = 0;
2630 
2631  G = Y5 + UV;
2632  if ((G >> 8) > 0)
2633  G = 255;
2634  else if (G < 0)
2635  G = 0;
2636 
2637  B = Y5 + U5;
2638  if ((B >> 8) > 0)
2639  B = 255;
2640  else if (B < 0)
2641  B = 0;
2642 
2643  *rgba++ = (unsigned char)R;
2644  *rgba++ = (unsigned char)G;
2645  *rgba++ = (unsigned char)B;
2646  *rgba++ = vpRGBa::alpha_default;
2647 
2648  //---
2649  R = Y6 + V2;
2650  if ((R >> 8) > 0)
2651  R = 255;
2652  else if (R < 0)
2653  R = 0;
2654 
2655  G = Y6 + UV;
2656  if ((G >> 8) > 0)
2657  G = 255;
2658  else if (G < 0)
2659  G = 0;
2660 
2661  B = Y6 + U5;
2662  if ((B >> 8) > 0)
2663  B = 255;
2664  else if (B < 0)
2665  B = 0;
2666 
2667  *rgba++ = (unsigned char)R;
2668  *rgba++ = (unsigned char)G;
2669  *rgba++ = (unsigned char)B;
2670  *rgba++ = vpRGBa::alpha_default;
2671 
2672  //---
2673  R = Y7 + V2;
2674  if ((R >> 8) > 0)
2675  R = 255;
2676  else if (R < 0)
2677  R = 0;
2678 
2679  G = Y7 + UV;
2680  if ((G >> 8) > 0)
2681  G = 255;
2682  else if (G < 0)
2683  G = 0;
2684 
2685  B = Y7 + U5;
2686  if ((B >> 8) > 0)
2687  B = 255;
2688  else if (B < 0)
2689  B = 0;
2690 
2691  *rgba++ = (unsigned char)R;
2692  *rgba++ = (unsigned char)G;
2693  *rgba++ = (unsigned char)B;
2694  *rgba = vpRGBa::alpha_default;
2695  rgba = rgba + 4 * width - 15;
2696 
2697  R = Y8 + V2;
2698  if ((R >> 8) > 0)
2699  R = 255;
2700  else if (R < 0)
2701  R = 0;
2702 
2703  G = Y8 + UV;
2704  if ((G >> 8) > 0)
2705  G = 255;
2706  else if (G < 0)
2707  G = 0;
2708 
2709  B = Y8 + U5;
2710  if ((B >> 8) > 0)
2711  B = 255;
2712  else if (B < 0)
2713  B = 0;
2714 
2715  *rgba++ = (unsigned char)R;
2716  *rgba++ = (unsigned char)G;
2717  *rgba++ = (unsigned char)B;
2718  *rgba++ = vpRGBa::alpha_default;
2719 
2720  //---
2721  R = Y9 + V2;
2722  if ((R >> 8) > 0)
2723  R = 255;
2724  else if (R < 0)
2725  R = 0;
2726 
2727  G = Y9 + UV;
2728  if ((G >> 8) > 0)
2729  G = 255;
2730  else if (G < 0)
2731  G = 0;
2732 
2733  B = Y9 + U5;
2734  if ((B >> 8) > 0)
2735  B = 255;
2736  else if (B < 0)
2737  B = 0;
2738 
2739  *rgba++ = (unsigned char)R;
2740  *rgba++ = (unsigned char)G;
2741  *rgba++ = (unsigned char)B;
2742  *rgba++ = vpRGBa::alpha_default;
2743 
2744  //---
2745  R = Y10 + V2;
2746  if ((R >> 8) > 0)
2747  R = 255;
2748  else if (R < 0)
2749  R = 0;
2750 
2751  G = Y10 + UV;
2752  if ((G >> 8) > 0)
2753  G = 255;
2754  else if (G < 0)
2755  G = 0;
2756 
2757  B = Y10 + U5;
2758  if ((B >> 8) > 0)
2759  B = 255;
2760  else if (B < 0)
2761  B = 0;
2762 
2763  *rgba++ = (unsigned char)R;
2764  *rgba++ = (unsigned char)G;
2765  *rgba++ = (unsigned char)B;
2766  *rgba++ = vpRGBa::alpha_default;
2767 
2768  //---
2769  R = Y11 + V2;
2770  if ((R >> 8) > 0)
2771  R = 255;
2772  else if (R < 0)
2773  R = 0;
2774 
2775  G = Y11 + UV;
2776  if ((G >> 8) > 0)
2777  G = 255;
2778  else if (G < 0)
2779  G = 0;
2780 
2781  B = Y11 + U5;
2782  if ((B >> 8) > 0)
2783  B = 255;
2784  else if (B < 0)
2785  B = 0;
2786 
2787  *rgba++ = (unsigned char)R;
2788  *rgba++ = (unsigned char)G;
2789  *rgba++ = (unsigned char)B;
2790  *rgba = vpRGBa::alpha_default;
2791  rgba = rgba + 4 * width - 15;
2792 
2793  R = Y12 + V2;
2794  if ((R >> 8) > 0)
2795  R = 255;
2796  else if (R < 0)
2797  R = 0;
2798 
2799  G = Y12 + UV;
2800  if ((G >> 8) > 0)
2801  G = 255;
2802  else if (G < 0)
2803  G = 0;
2804 
2805  B = Y12 + U5;
2806  if ((B >> 8) > 0)
2807  B = 255;
2808  else if (B < 0)
2809  B = 0;
2810 
2811  *rgba++ = (unsigned char)R;
2812  *rgba++ = (unsigned char)G;
2813  *rgba++ = (unsigned char)B;
2814  *rgba++ = vpRGBa::alpha_default;
2815 
2816  //---
2817  R = Y13 + V2;
2818  if ((R >> 8) > 0)
2819  R = 255;
2820  else if (R < 0)
2821  R = 0;
2822 
2823  G = Y13 + UV;
2824  if ((G >> 8) > 0)
2825  G = 255;
2826  else if (G < 0)
2827  G = 0;
2828 
2829  B = Y13 + U5;
2830  if ((B >> 8) > 0)
2831  B = 255;
2832  else if (B < 0)
2833  B = 0;
2834 
2835  *rgba++ = (unsigned char)R;
2836  *rgba++ = (unsigned char)G;
2837  *rgba++ = (unsigned char)B;
2838  *rgba++ = vpRGBa::alpha_default;
2839 
2840  //---
2841  R = Y14 + V2;
2842  if ((R >> 8) > 0)
2843  R = 255;
2844  else if (R < 0)
2845  R = 0;
2846 
2847  G = Y14 + UV;
2848  if ((G >> 8) > 0)
2849  G = 255;
2850  else if (G < 0)
2851  G = 0;
2852 
2853  B = Y14 + U5;
2854  if ((B >> 8) > 0)
2855  B = 255;
2856  else if (B < 0)
2857  B = 0;
2858 
2859  *rgba++ = (unsigned char)R;
2860  *rgba++ = (unsigned char)G;
2861  *rgba++ = (unsigned char)B;
2862  *rgba++ = vpRGBa::alpha_default;
2863 
2864  //---
2865  R = Y15 + V2;
2866  if ((R >> 8) > 0)
2867  R = 255;
2868  else if (R < 0)
2869  R = 0;
2870 
2871  G = Y15 + UV;
2872  if ((G >> 8) > 0)
2873  G = 255;
2874  else if (G < 0)
2875  G = 0;
2876 
2877  B = Y15 + U5;
2878  if ((B >> 8) > 0)
2879  B = 255;
2880  else if (B < 0)
2881  B = 0;
2882 
2883  *rgba++ = (unsigned char)R;
2884  *rgba++ = (unsigned char)G;
2885  *rgba++ = (unsigned char)B;
2886  *rgba = vpRGBa::alpha_default;
2887  rgba = rgba - 12 * width + 1;
2888  }
2889  yuv += 3 * width;
2890  rgba += 12 * width;
2891  }
2892 }
2893 
2897 void vpImageConvert::YVU9ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int height, unsigned int width)
2898 {
2899  // std::cout << "call optimized ConvertYVU9ToRGB()" << std::endl;
2900  int U, V, R, G, B, V2, U5, UV;
2901  int Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9, Y10, Y11, Y12, Y13, Y14, Y15;
2902  unsigned int size = width * height;
2903  unsigned char *iV = yuv + size;
2904  unsigned char *iU = yuv + 17 * size / 16;
2905  for (unsigned int i = 0; i < height / 4; i++) {
2906  for (unsigned int j = 0; j < width / 4; j++) {
2907  U = (int)((*iU++ - 128) * 0.354);
2908  U5 = 5 * U;
2909  V = (int)((*iV++ - 128) * 0.707);
2910  V2 = 2 * V;
2911  UV = -U - V;
2912  Y0 = *yuv++;
2913  Y1 = *yuv++;
2914  Y2 = *yuv++;
2915  Y3 = *yuv;
2916  yuv = yuv + width - 3;
2917  Y4 = *yuv++;
2918  Y5 = *yuv++;
2919  Y6 = *yuv++;
2920  Y7 = *yuv;
2921  yuv = yuv + width - 3;
2922  Y8 = *yuv++;
2923  Y9 = *yuv++;
2924  Y10 = *yuv++;
2925  Y11 = *yuv;
2926  yuv = yuv + width - 3;
2927  Y12 = *yuv++;
2928  Y13 = *yuv++;
2929  Y14 = *yuv++;
2930  Y15 = *yuv;
2931  yuv = yuv - 3 * width + 1;
2932 
2933  // Original equations
2934  // R = Y + 1.402 V
2935  // G = Y - 0.344 U - 0.714 V
2936  // B = Y + 1.772 U
2937  R = Y0 + V2;
2938  if ((R >> 8) > 0)
2939  R = 255;
2940  else if (R < 0)
2941  R = 0;
2942 
2943  G = Y0 + UV;
2944  if ((G >> 8) > 0)
2945  G = 255;
2946  else if (G < 0)
2947  G = 0;
2948 
2949  B = Y0 + U5;
2950  if ((B >> 8) > 0)
2951  B = 255;
2952  else if (B < 0)
2953  B = 0;
2954 
2955  *rgb++ = (unsigned char)R;
2956  *rgb++ = (unsigned char)G;
2957  *rgb++ = (unsigned char)B;
2958 
2959  //---
2960  R = Y1 + V2;
2961  if ((R >> 8) > 0)
2962  R = 255;
2963  else if (R < 0)
2964  R = 0;
2965 
2966  G = Y1 + UV;
2967  if ((G >> 8) > 0)
2968  G = 255;
2969  else if (G < 0)
2970  G = 0;
2971 
2972  B = Y1 + U5;
2973  if ((B >> 8) > 0)
2974  B = 255;
2975  else if (B < 0)
2976  B = 0;
2977 
2978  *rgb++ = (unsigned char)R;
2979  *rgb++ = (unsigned char)G;
2980  *rgb++ = (unsigned char)B;
2981 
2982  //---
2983  R = Y2 + V2;
2984  if ((R >> 8) > 0)
2985  R = 255;
2986  else if (R < 0)
2987  R = 0;
2988 
2989  G = Y2 + UV;
2990  if ((G >> 8) > 0)
2991  G = 255;
2992  else if (G < 0)
2993  G = 0;
2994 
2995  B = Y2 + U5;
2996  if ((B >> 8) > 0)
2997  B = 255;
2998  else if (B < 0)
2999  B = 0;
3000 
3001  *rgb++ = (unsigned char)R;
3002  *rgb++ = (unsigned char)G;
3003  *rgb++ = (unsigned char)B;
3004 
3005  //---
3006  R = Y3 + V2;
3007  if ((R >> 8) > 0)
3008  R = 255;
3009  else if (R < 0)
3010  R = 0;
3011 
3012  G = Y3 + UV;
3013  if ((G >> 8) > 0)
3014  G = 255;
3015  else if (G < 0)
3016  G = 0;
3017 
3018  B = Y3 + U5;
3019  if ((B >> 8) > 0)
3020  B = 255;
3021  else if (B < 0)
3022  B = 0;
3023 
3024  *rgb++ = (unsigned char)R;
3025  *rgb++ = (unsigned char)G;
3026  *rgb = (unsigned char)B;
3027  rgb = rgb + 3 * width - 11;
3028 
3029  R = Y4 + V2;
3030  if ((R >> 8) > 0)
3031  R = 255;
3032  else if (R < 0)
3033  R = 0;
3034 
3035  G = Y4 + UV;
3036  if ((G >> 8) > 0)
3037  G = 255;
3038  else if (G < 0)
3039  G = 0;
3040 
3041  B = Y4 + U5;
3042  if ((B >> 8) > 0)
3043  B = 255;
3044  else if (B < 0)
3045  B = 0;
3046 
3047  *rgb++ = (unsigned char)R;
3048  *rgb++ = (unsigned char)G;
3049  *rgb++ = (unsigned char)B;
3050 
3051  //---
3052  R = Y5 + V2;
3053  if ((R >> 8) > 0)
3054  R = 255;
3055  else if (R < 0)
3056  R = 0;
3057 
3058  G = Y5 + UV;
3059  if ((G >> 8) > 0)
3060  G = 255;
3061  else if (G < 0)
3062  G = 0;
3063 
3064  B = Y5 + U5;
3065  if ((B >> 8) > 0)
3066  B = 255;
3067  else if (B < 0)
3068  B = 0;
3069 
3070  *rgb++ = (unsigned char)R;
3071  *rgb++ = (unsigned char)G;
3072  *rgb++ = (unsigned char)B;
3073 
3074  //---
3075  R = Y6 + V2;
3076  if ((R >> 8) > 0)
3077  R = 255;
3078  else if (R < 0)
3079  R = 0;
3080 
3081  G = Y6 + UV;
3082  if ((G >> 8) > 0)
3083  G = 255;
3084  else if (G < 0)
3085  G = 0;
3086 
3087  B = Y6 + U5;
3088  if ((B >> 8) > 0)
3089  B = 255;
3090  else if (B < 0)
3091  B = 0;
3092 
3093  *rgb++ = (unsigned char)R;
3094  *rgb++ = (unsigned char)G;
3095  *rgb++ = (unsigned char)B;
3096 
3097  //---
3098  R = Y7 + V2;
3099  if ((R >> 8) > 0)
3100  R = 255;
3101  else if (R < 0)
3102  R = 0;
3103 
3104  G = Y7 + UV;
3105  if ((G >> 8) > 0)
3106  G = 255;
3107  else if (G < 0)
3108  G = 0;
3109 
3110  B = Y7 + U5;
3111  if ((B >> 8) > 0)
3112  B = 255;
3113  else if (B < 0)
3114  B = 0;
3115 
3116  *rgb++ = (unsigned char)R;
3117  *rgb++ = (unsigned char)G;
3118  *rgb = (unsigned char)B;
3119  rgb = rgb + 3 * width - 11;
3120 
3121  R = Y8 + V2;
3122  if ((R >> 8) > 0)
3123  R = 255;
3124  else if (R < 0)
3125  R = 0;
3126 
3127  G = Y8 + UV;
3128  if ((G >> 8) > 0)
3129  G = 255;
3130  else if (G < 0)
3131  G = 0;
3132 
3133  B = Y8 + U5;
3134  if ((B >> 8) > 0)
3135  B = 255;
3136  else if (B < 0)
3137  B = 0;
3138 
3139  *rgb++ = (unsigned char)R;
3140  *rgb++ = (unsigned char)G;
3141  *rgb++ = (unsigned char)B;
3142 
3143  //---
3144  R = Y9 + V2;
3145  if ((R >> 8) > 0)
3146  R = 255;
3147  else if (R < 0)
3148  R = 0;
3149 
3150  G = Y9 + UV;
3151  if ((G >> 8) > 0)
3152  G = 255;
3153  else if (G < 0)
3154  G = 0;
3155 
3156  B = Y9 + U5;
3157  if ((B >> 8) > 0)
3158  B = 255;
3159  else if (B < 0)
3160  B = 0;
3161 
3162  *rgb++ = (unsigned char)R;
3163  *rgb++ = (unsigned char)G;
3164  *rgb++ = (unsigned char)B;
3165 
3166  //---
3167  R = Y10 + V2;
3168  if ((R >> 8) > 0)
3169  R = 255;
3170  else if (R < 0)
3171  R = 0;
3172 
3173  G = Y10 + UV;
3174  if ((G >> 8) > 0)
3175  G = 255;
3176  else if (G < 0)
3177  G = 0;
3178 
3179  B = Y10 + U5;
3180  if ((B >> 8) > 0)
3181  B = 255;
3182  else if (B < 0)
3183  B = 0;
3184 
3185  *rgb++ = (unsigned char)R;
3186  *rgb++ = (unsigned char)G;
3187  *rgb++ = (unsigned char)B;
3188 
3189  //---
3190  R = Y11 + V2;
3191  if ((R >> 8) > 0)
3192  R = 255;
3193  else if (R < 0)
3194  R = 0;
3195 
3196  G = Y11 + UV;
3197  if ((G >> 8) > 0)
3198  G = 255;
3199  else if (G < 0)
3200  G = 0;
3201 
3202  B = Y11 + U5;
3203  if ((B >> 8) > 0)
3204  B = 255;
3205  else if (B < 0)
3206  B = 0;
3207 
3208  *rgb++ = (unsigned char)R;
3209  *rgb++ = (unsigned char)G;
3210  *rgb = (unsigned char)B;
3211  rgb = rgb + 3 * width - 11;
3212 
3213  R = Y12 + V2;
3214  if ((R >> 8) > 0)
3215  R = 255;
3216  else if (R < 0)
3217  R = 0;
3218 
3219  G = Y12 + UV;
3220  if ((G >> 8) > 0)
3221  G = 255;
3222  else if (G < 0)
3223  G = 0;
3224 
3225  B = Y12 + U5;
3226  if ((B >> 8) > 0)
3227  B = 255;
3228  else if (B < 0)
3229  B = 0;
3230 
3231  *rgb++ = (unsigned char)R;
3232  *rgb++ = (unsigned char)G;
3233  *rgb++ = (unsigned char)B;
3234 
3235  //---
3236  R = Y13 + V2;
3237  if ((R >> 8) > 0)
3238  R = 255;
3239  else if (R < 0)
3240  R = 0;
3241 
3242  G = Y13 + UV;
3243  if ((G >> 8) > 0)
3244  G = 255;
3245  else if (G < 0)
3246  G = 0;
3247 
3248  B = Y13 + U5;
3249  if ((B >> 8) > 0)
3250  B = 255;
3251  else if (B < 0)
3252  B = 0;
3253 
3254  *rgb++ = (unsigned char)R;
3255  *rgb++ = (unsigned char)G;
3256  *rgb++ = (unsigned char)B;
3257 
3258  //---
3259  R = Y14 + V2;
3260  if ((R >> 8) > 0)
3261  R = 255;
3262  else if (R < 0)
3263  R = 0;
3264 
3265  G = Y14 + UV;
3266  if ((G >> 8) > 0)
3267  G = 255;
3268  else if (G < 0)
3269  G = 0;
3270 
3271  B = Y14 + U5;
3272  if ((B >> 8) > 0)
3273  B = 255;
3274  else if (B < 0)
3275  B = 0;
3276 
3277  *rgb++ = (unsigned char)R;
3278  *rgb++ = (unsigned char)G;
3279  *rgb++ = (unsigned char)B;
3280 
3281  //---
3282  R = Y15 + V2;
3283  if ((R >> 8) > 0)
3284  R = 255;
3285  else if (R < 0)
3286  R = 0;
3287 
3288  G = Y15 + UV;
3289  if ((G >> 8) > 0)
3290  G = 255;
3291  else if (G < 0)
3292  G = 0;
3293 
3294  B = Y15 + U5;
3295  if ((B >> 8) > 0)
3296  B = 255;
3297  else if (B < 0)
3298  B = 0;
3299 
3300  *rgb++ = (unsigned char)R;
3301  *rgb++ = (unsigned char)G;
3302  *rgb++ = (unsigned char)B;
3303  rgb = rgb - 9 * width + 1;
3304  }
3305  yuv += 3 * width;
3306  rgb += 9 * width;
3307  }
3308 }
3309 
3315 void vpImageConvert::RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
3316 {
3317  RGBToRGBa(rgb, rgba, size, 1, false);
3318 }
3319 
3329 void vpImageConvert::RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int width, unsigned int height,
3330  bool flip)
3331 {
3332  if (!flip) {
3333  SimdBgrToBgra(rgb, width, height, width * 3, rgba, width * 4, vpRGBa::alpha_default);
3334  } else {
3335  // if we have to flip the image, we start from the end last scanline so the
3336  // step is negative
3337  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
3338 
3339  // starting source address = last line if we need to flip the image
3340  unsigned char *src = (flip) ? (rgb + (width * height * 3) + lineStep) : rgb;
3341 
3342  unsigned int j = 0;
3343  unsigned int i = 0;
3344 
3345  for (i = 0; i < height; i++) {
3346  unsigned char *line = src;
3347  for (j = 0; j < width; j++) {
3348  *rgba++ = *(line++);
3349  *rgba++ = *(line++);
3350  *rgba++ = *(line++);
3351  *rgba++ = vpRGBa::alpha_default;
3352  }
3353  // go to the next line
3354  src += lineStep;
3355  }
3356  }
3357 }
3358 
3366 void vpImageConvert::RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
3367 {
3368  SimdBgraToBgr(rgba, size, 1, size * 4, rgb, size * 3);
3369 }
3370 
3376 void vpImageConvert::RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int size)
3377 {
3378  RGBToGrey(rgb, grey, size, 1, false);
3379 }
3380 
3388 void vpImageConvert::RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height,
3389  bool flip)
3390 {
3391  if (!flip) {
3392  SimdRgbToGray(rgb, width, height, width * 3, grey, width);
3393  } else {
3394  // if we have to flip the image, we start from the end last scanline so
3395  // the step is negative
3396  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
3397 
3398  // starting source address = last line if we need to flip the image
3399  unsigned char *src = (flip) ? rgb + (width * height * 3) + lineStep : rgb;
3400 
3401  unsigned int j = 0;
3402  unsigned int i = 0;
3403 
3404  unsigned r, g, b;
3405 
3406  for (i = 0; i < height; i++) {
3407  unsigned char *line = src;
3408  for (j = 0; j < width; j++) {
3409  r = *(line++);
3410  g = *(line++);
3411  b = *(line++);
3412  *grey++ = (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
3413  }
3414 
3415  // go to the next line
3416  src += lineStep;
3417  }
3418  }
3419 }
3420 
3428 void vpImageConvert::RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int width, unsigned int height, unsigned int
3429  #if defined _OPENMP
3430  nThreads
3431  #endif
3432  )
3433 {
3434 #if defined _OPENMP
3435  if (nThreads > 0) {
3436  omp_set_num_threads(static_cast<int>(nThreads));
3437  }
3438  #pragma omp parallel for
3439 #endif
3440  for (int i = 0; i < static_cast<int>(height); i++) {
3441  SimdRgbaToGray(rgba + i*width*4, width, 1, width*4, grey + i*width, width);
3442  }
3443 }
3444 
3452 void vpImageConvert::RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int size)
3453 {
3454  SimdRgbaToGray(rgba, size, 1, size*4, grey, size);
3455 }
3456 
3463 void vpImageConvert::GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int width, unsigned int height)
3464 {
3465  SimdGrayToBgra(grey, width, height, width, rgba, width * sizeof(vpRGBa), vpRGBa::alpha_default);
3466 }
3467 
3474 void vpImageConvert::GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int size)
3475 {
3476  GreyToRGBa(grey, rgba, size, 1);
3477 }
3478 
3484 void vpImageConvert::GreyToRGB(unsigned char *grey, unsigned char *rgb, unsigned int size)
3485 {
3486  SimdGrayToBgr(grey, size, 1, size, rgb, size * 3);
3487 }
3488 
3498 void vpImageConvert::BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height,
3499  bool flip)
3500 {
3501  if (!flip) {
3502  SimdBgrToRgba(bgr, width, height, width*3, rgba, width * sizeof(vpRGBa), vpRGBa::alpha_default);
3503  } else {
3504  // if we have to flip the image, we start from the end last scanline so the
3505  // step is negative
3506  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
3507 
3508  // starting source address = last line if we need to flip the image
3509  unsigned char *src = (flip) ? (bgr + (width * height * 3) + lineStep) : bgr;
3510 
3511  for (unsigned int i = 0; i < height; i++) {
3512  unsigned char *line = src;
3513  for (unsigned int j = 0; j < width; j++) {
3514  *rgba++ = *(line + 2);
3515  *rgba++ = *(line + 1);
3516  *rgba++ = *(line + 0);
3517  *rgba++ = vpRGBa::alpha_default;
3518 
3519  line += 3;
3520  }
3521  // go to the next line
3522  src += lineStep;
3523  }
3524  }
3525 }
3526 
3534 void vpImageConvert::BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height,
3535  bool flip, unsigned int
3536  #if defined _OPENMP
3537  nThreads
3538  #endif
3539  )
3540 {
3541  if (!flip) {
3542 #if defined _OPENMP
3543  if (nThreads > 0) {
3544  omp_set_num_threads(static_cast<int>(nThreads));
3545  }
3546 #pragma omp parallel for
3547 #endif
3548  for (int i = 0; i < static_cast<int>(height); i++) {
3549  SimdBgrToGray(bgr + i*width*3, width, 1, width * 3, grey + i*width, width);
3550  }
3551  } else {
3552  // if we have to flip the image, we start from the end last scanline so
3553  // the step is negative
3554  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
3555 
3556  // starting source address = last line if we need to flip the image
3557  unsigned char *src = (flip) ? bgr + (width * height * 3) + lineStep : bgr;
3558 
3559  for (unsigned int i = 0; i < height; i++) {
3560  unsigned char *line = src;
3561  for (unsigned int j = 0; j < width; j++) {
3562  *grey++ = (unsigned char)(0.2126 * *(line + 2) + 0.7152 * *(line + 1) + 0.0722 * *(line + 0));
3563  line += 3;
3564  }
3565 
3566  // go to the next line
3567  src += lineStep;
3568  }
3569  }
3570 }
3571 
3575 void vpImageConvert::computeYCbCrLUT()
3576 {
3577  if (YCbCrLUTcomputed == false) {
3578  int index = 256;
3579 
3580  while (index--) {
3581 
3582  int aux = index - 128;
3583  vpImageConvert::vpCrr[index] = (int)(364.6610 * aux) >> 8;
3584  vpImageConvert::vpCgb[index] = (int)(-89.8779 * aux) >> 8;
3585  vpImageConvert::vpCgr[index] = (int)(-185.8154 * aux) >> 8;
3586  vpImageConvert::vpCbb[index] = (int)(460.5724 * aux) >> 8;
3587  }
3588 
3589  YCbCrLUTcomputed = true;
3590  }
3591 }
3592 
3609 void vpImageConvert::YCbCrToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
3610 {
3611  unsigned char *cbv;
3612  unsigned char *crv;
3613  unsigned char *pt_ycbcr = ycbcr;
3614  unsigned char *pt_rgb = rgb;
3615  cbv = pt_ycbcr + 1;
3616  crv = pt_ycbcr + 3;
3617 
3618  vpImageConvert::computeYCbCrLUT();
3619 
3620  int col = 0;
3621 
3622  while (size--) {
3623  int val_r, val_g, val_b;
3624  if (!(col++ % 2)) {
3625  cbv = pt_ycbcr + 1;
3626  crv = pt_ycbcr + 3;
3627  }
3628 
3629  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
3630  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
3631  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
3632 
3633  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
3634 
3635  *pt_rgb++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
3636  *pt_rgb++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
3637  *pt_rgb++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
3638 
3639  pt_ycbcr += 2;
3640  }
3641 }
3642 
3663 void vpImageConvert::YCbCrToRGBa(unsigned char *ycbcr, unsigned char *rgba, unsigned int size)
3664 {
3665  unsigned char *cbv;
3666  unsigned char *crv;
3667  unsigned char *pt_ycbcr = ycbcr;
3668  unsigned char *pt_rgba = rgba;
3669  cbv = pt_ycbcr + 1;
3670  crv = pt_ycbcr + 3;
3671 
3672  vpImageConvert::computeYCbCrLUT();
3673 
3674  int col = 0;
3675 
3676  while (size--) {
3677  int val_r, val_g, val_b;
3678  if (!(col++ % 2)) {
3679  cbv = pt_ycbcr + 1;
3680  crv = pt_ycbcr + 3;
3681  }
3682 
3683  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
3684  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
3685  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
3686 
3687  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
3688 
3689  *pt_rgba++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
3690  *pt_rgba++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
3691  *pt_rgba++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
3692  *pt_rgba++ = vpRGBa::alpha_default;
3693 
3694  pt_ycbcr += 2;
3695  }
3696 }
3697 
3712 void vpImageConvert::YCbCrToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
3713 {
3714  unsigned int i = 0, j = 0;
3715 
3716  while (j < size * 2) {
3717  grey[i++] = yuv[j];
3718  grey[i++] = yuv[j + 2];
3719  j += 4;
3720  }
3721 }
3722 
3739 void vpImageConvert::YCrCbToRGB(unsigned char *ycrcb, unsigned char *rgb, unsigned int size)
3740 {
3741  unsigned char *cbv;
3742  unsigned char *crv;
3743  unsigned char *pt_ycbcr = ycrcb;
3744  unsigned char *pt_rgb = rgb;
3745  crv = pt_ycbcr + 1;
3746  cbv = pt_ycbcr + 3;
3747 
3748  vpImageConvert::computeYCbCrLUT();
3749 
3750  int col = 0;
3751 
3752  while (size--) {
3753  int val_r, val_g, val_b;
3754  if (!(col++ % 2)) {
3755  crv = pt_ycbcr + 1;
3756  cbv = pt_ycbcr + 3;
3757  }
3758 
3759  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
3760  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
3761  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
3762 
3763  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
3764 
3765  *pt_rgb++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
3766  *pt_rgb++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
3767  *pt_rgb++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
3768 
3769  pt_ycbcr += 2;
3770  }
3771 }
3772 
3792 void vpImageConvert::YCrCbToRGBa(unsigned char *ycrcb, unsigned char *rgba, unsigned int size)
3793 {
3794  unsigned char *cbv;
3795  unsigned char *crv;
3796  unsigned char *pt_ycbcr = ycrcb;
3797  unsigned char *pt_rgba = rgba;
3798  crv = pt_ycbcr + 1;
3799  cbv = pt_ycbcr + 3;
3800 
3801  vpImageConvert::computeYCbCrLUT();
3802 
3803  int col = 0;
3804 
3805  while (size--) {
3806  int val_r, val_g, val_b;
3807  if (!(col++ % 2)) {
3808  crv = pt_ycbcr + 1;
3809  cbv = pt_ycbcr + 3;
3810  }
3811 
3812  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
3813  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
3814  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
3815 
3816  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
3817 
3818  *pt_rgba++ = (val_r < 0) ? 0u : ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
3819  *pt_rgba++ = (val_g < 0) ? 0u : ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
3820  *pt_rgba++ = (val_b < 0) ? 0u : ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
3821  *pt_rgba++ = vpRGBa::alpha_default;
3822 
3823  pt_ycbcr += 2;
3824  }
3825 }
3826 
3865 {
3866  if (src.getSize() > 0) {
3867  if (pR) {
3868  pR->resize(src.getHeight(), src.getWidth());
3869  }
3870  if (pG) {
3871  pG->resize(src.getHeight(), src.getWidth());
3872  }
3873  if (pB) {
3874  pB->resize(src.getHeight(), src.getWidth());
3875  }
3876  if (pa) {
3877  pa->resize(src.getHeight(), src.getWidth());
3878  }
3879 
3880  unsigned char *ptrR = pR ? pR->bitmap : new unsigned char[src.getSize()];
3881  unsigned char *ptrG = pG ? pG->bitmap : new unsigned char[src.getSize()];
3882  unsigned char *ptrB = pB ? pB->bitmap : new unsigned char[src.getSize()];
3883  unsigned char *ptrA = pa ? pa->bitmap : new unsigned char[src.getSize()];
3884 
3885  SimdDeinterleaveBgra(reinterpret_cast<unsigned char*>(src.bitmap), src.getWidth()*sizeof(vpRGBa),
3886  src.getWidth(), src.getHeight(),
3887  ptrR, src.getWidth(),
3888  ptrG, src.getWidth(),
3889  ptrB, src.getWidth(),
3890  ptrA, src.getWidth());
3891 
3892  if (!pR) {
3893  delete[] ptrR;
3894  }
3895  if (!pG) {
3896  delete[] ptrG;
3897  }
3898  if (!pB) {
3899  delete[] ptrB;
3900  }
3901  if (!pa) {
3902  delete[] ptrA;
3903  }
3904  }
3905 }
3906 
3919 {
3920  // Check if the input channels have all the same dimensions
3921  std::map<unsigned int, unsigned int> mapOfWidths, mapOfHeights;
3922  if (R != NULL) {
3923  mapOfWidths[R->getWidth()]++;
3924  mapOfHeights[R->getHeight()]++;
3925  }
3926 
3927  if (G != NULL) {
3928  mapOfWidths[G->getWidth()]++;
3929  mapOfHeights[G->getHeight()]++;
3930  }
3931 
3932  if (B != NULL) {
3933  mapOfWidths[B->getWidth()]++;
3934  mapOfHeights[B->getHeight()]++;
3935  }
3936 
3937  if (a != NULL) {
3938  mapOfWidths[a->getWidth()]++;
3939  mapOfHeights[a->getHeight()]++;
3940  }
3941 
3942  if (mapOfWidths.size() == 1 && mapOfHeights.size() == 1) {
3943  unsigned int width = mapOfWidths.begin()->first;
3944  unsigned int height = mapOfHeights.begin()->first;
3945 
3946  RGBa.resize(height, width);
3947 
3948  if (R != NULL && G != NULL && B != NULL && a != NULL) {
3949  SimdInterleaveBgra(R->bitmap, width, G->bitmap, width, B->bitmap, width,
3950  a->bitmap, width, width, height, reinterpret_cast<uint8_t *>(RGBa.bitmap),
3951  width*sizeof(vpRGBa));
3952  } else {
3953  unsigned int size = width * height;
3954  for (unsigned int i = 0; i < size; i++) {
3955  if (R != NULL) {
3956  RGBa.bitmap[i].R = R->bitmap[i];
3957  }
3958 
3959  if (G != NULL) {
3960  RGBa.bitmap[i].G = G->bitmap[i];
3961  }
3962 
3963  if (B != NULL) {
3964  RGBa.bitmap[i].B = B->bitmap[i];
3965  }
3966 
3967  if (a != NULL) {
3968  RGBa.bitmap[i].A = a->bitmap[i];
3969  }
3970  }
3971  }
3972  } else {
3973  throw vpException(vpException::dimensionError, "Mismatched dimensions!");
3974  }
3975 }
3976 
3985 void vpImageConvert::MONO16ToGrey(unsigned char *grey16, unsigned char *grey, unsigned int size)
3986 {
3987  int i = (((int)size) << 1) - 1;
3988  int j = (int)size - 1;
3989 
3990  while (i >= 0) {
3991  int y = grey16[i--];
3992  grey[j--] = static_cast<unsigned char>((y + (grey16[i--] << 8)) >> 8);
3993  }
3994 }
3995 
4006 void vpImageConvert::MONO16ToRGBa(unsigned char *grey16, unsigned char *rgba, unsigned int size)
4007 {
4008  int i = (((int)size) << 1) - 1;
4009  int j = (int)(size * 4 - 1);
4010 
4011  while (i >= 0) {
4012  int y = grey16[i--];
4013  unsigned char v = static_cast<unsigned char>((y + (grey16[i--] << 8)) >> 8);
4014  rgba[j--] = vpRGBa::alpha_default;
4015  rgba[j--] = v;
4016  rgba[j--] = v;
4017  rgba[j--] = v;
4018  }
4019 }
4020 
4021 void vpImageConvert::HSV2RGB(const double *hue_, const double *saturation_, const double *value_, unsigned char *rgb,
4022  unsigned int size, unsigned int step)
4023 {
4024  for (unsigned int i = 0; i < size; i++) {
4025  double hue = hue_[i], saturation = saturation_[i], value = value_[i];
4026 
4027  if (vpMath::equal(saturation, 0.0, std::numeric_limits<double>::epsilon())) {
4028  hue = value;
4029  saturation = value;
4030  } else {
4031  double h = hue * 6.0;
4032  double s = saturation;
4033  double v = value;
4034 
4035  if (vpMath::equal(h, 6.0, std::numeric_limits<double>::epsilon())) {
4036  h = 0.0;
4037  }
4038 
4039  double f = h - (int)h;
4040  double p = v * (1.0 - s);
4041  double q = v * (1.0 - s * f);
4042  double t = v * (1.0 - s * (1.0 - f));
4043 
4044  switch ((int)h) {
4045  case 0:
4046  hue = v;
4047  saturation = t;
4048  value = p;
4049  break;
4050 
4051  case 1:
4052  hue = q;
4053  saturation = v;
4054  value = p;
4055  break;
4056 
4057  case 2:
4058  hue = p;
4059  saturation = v;
4060  value = t;
4061  break;
4062 
4063  case 3:
4064  hue = p;
4065  saturation = q;
4066  value = v;
4067  break;
4068 
4069  case 4:
4070  hue = t;
4071  saturation = p;
4072  value = v;
4073  break;
4074 
4075  default: // case 5:
4076  hue = v;
4077  saturation = p;
4078  value = q;
4079  break;
4080  }
4081  }
4082 
4083  rgb[i * step] = (unsigned char)vpMath::round(hue * 255.0);
4084  rgb[i * step + 1] = (unsigned char)vpMath::round(saturation * 255.0);
4085  rgb[i * step + 2] = (unsigned char)vpMath::round(value * 255.0);
4086  if (step == 4) // alpha
4087  rgb[i * step + 3] = vpRGBa::alpha_default;
4088  }
4089 }
4090 
4091 void vpImageConvert::RGB2HSV(const unsigned char *rgb, double *hue, double *saturation, double *value,
4092  unsigned int size, unsigned int step)
4093 {
4094  for (unsigned int i = 0; i < size; i++) {
4095  double red, green, blue;
4096  double h, s, v;
4097  double min, max;
4098 
4099  red = rgb[i * step] / 255.0;
4100  green = rgb[i * step + 1] / 255.0;
4101  blue = rgb[i * step + 2] / 255.0;
4102 
4103  if (red > green) {
4104  max = ((std::max))(red, blue);
4105  min = ((std::min))(green, blue);
4106  } else {
4107  max = ((std::max))(green, blue);
4108  min = ((std::min))(red, blue);
4109  }
4110 
4111  v = max;
4112 
4113  if (!vpMath::equal(max, 0.0, std::numeric_limits<double>::epsilon())) {
4114  s = (max - min) / max;
4115  } else {
4116  s = 0.0;
4117  }
4118 
4119  if (vpMath::equal(s, 0.0, std::numeric_limits<double>::epsilon())) {
4120  h = 0.0;
4121  } else {
4122  double delta = max - min;
4123  if (vpMath::equal(delta, 0.0, std::numeric_limits<double>::epsilon())) {
4124  delta = 1.0;
4125  }
4126 
4127  if (vpMath::equal(red, max, std::numeric_limits<double>::epsilon())) {
4128  h = (green - blue) / delta;
4129  } else if (vpMath::equal(green, max, std::numeric_limits<double>::epsilon())) {
4130  h = 2 + (blue - red) / delta;
4131  } else {
4132  h = 4 + (red - green) / delta;
4133  }
4134 
4135  h /= 6.0;
4136  if (h < 0.0) {
4137  h += 1.0;
4138  } else if (h > 1.0) {
4139  h -= 1.0;
4140  }
4141  }
4142 
4143  hue[i] = h;
4144  saturation[i] = s;
4145  value[i] = v;
4146  }
4147 }
4148 
4161 void vpImageConvert::HSVToRGBa(const double *hue, const double *saturation, const double *value, unsigned char *rgba,
4162  unsigned int size)
4163 {
4164  vpImageConvert::HSV2RGB(hue, saturation, value, rgba, size, 4);
4165 }
4166 
4179 void vpImageConvert::HSVToRGBa(const unsigned char *hue, const unsigned char *saturation, const unsigned char *value,
4180  unsigned char *rgba, unsigned int size)
4181 {
4182  for (unsigned int i = 0; i < size; i++) {
4183  double h = hue[i] / 255.0, s = saturation[i] / 255.0, v = value[i] / 255.0;
4184 
4185  vpImageConvert::HSVToRGBa(&h, &s, &v, (rgba + i * 4), 1);
4186  }
4187 }
4188 
4201 void vpImageConvert::RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value,
4202  unsigned int size)
4203 {
4204  vpImageConvert::RGB2HSV(rgba, hue, saturation, value, size, 4);
4205 }
4206 
4218 void vpImageConvert::RGBaToHSV(const unsigned char *rgba, unsigned char *hue, unsigned char *saturation,
4219  unsigned char *value, unsigned int size)
4220 {
4221  for (unsigned int i = 0; i < size; i++) {
4222  double h, s, v;
4223  vpImageConvert::RGBaToHSV((rgba + i * 4), &h, &s, &v, 1);
4224 
4225  hue[i] = (unsigned char)(255.0 * h);
4226  saturation[i] = (unsigned char)(255.0 * s);
4227  value[i] = (unsigned char)(255.0 * v);
4228  }
4229 }
4230 
4240 void vpImageConvert::HSVToRGB(const double *hue, const double *saturation, const double *value, unsigned char *rgb,
4241  unsigned int size)
4242 {
4243  vpImageConvert::HSV2RGB(hue, saturation, value, rgb, size, 3);
4244 }
4245 
4255 void vpImageConvert::HSVToRGB(const unsigned char *hue, const unsigned char *saturation, const unsigned char *value,
4256  unsigned char *rgb, unsigned int size)
4257 {
4258  for (unsigned int i = 0; i < size; i++) {
4259  double h = hue[i] / 255.0, s = saturation[i] / 255.0, v = value[i] / 255.0;
4260 
4261  vpImageConvert::HSVToRGB(&h, &s, &v, (rgb + i * 3), 1);
4262  }
4263 }
4264 
4276 void vpImageConvert::RGBToHSV(const unsigned char *rgb, double *hue, double *saturation, double *value,
4277  unsigned int size)
4278 {
4279  vpImageConvert::RGB2HSV(rgb, hue, saturation, value, size, 3);
4280 }
4281 
4292 void vpImageConvert::RGBToHSV(const unsigned char *rgb, unsigned char *hue, unsigned char *saturation,
4293  unsigned char *value, unsigned int size)
4294 {
4295  for (unsigned int i = 0; i < size; i++) {
4296  double h, s, v;
4297 
4298  vpImageConvert::RGBToHSV((rgb + i * 3), &h, &s, &v, 1);
4299 
4300  hue[i] = (unsigned char)(255.0 * h);
4301  saturation[i] = (unsigned char)(255.0 * s);
4302  value[i] = (unsigned char)(255.0 * v);
4303  }
4304 }
static void BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static void YUYVToRGBa(unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height)
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:800
static void HSVToRGB(const double *hue, const double *saturation, const double *value, unsigned char *rgb, unsigned int size)
unsigned char B
Blue component.
Definition: vpRGBa.h:150
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
unsigned int getRows() const
Definition: vpImage.h:218
static void RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value, unsigned int size)
Type * bitmap
points toward the bitmap
Definition: vpImage.h:143
static void MONO16ToGrey(unsigned char *grey16, unsigned char *grey, unsigned int size)
static bool equal(double x, double y, double s=0.001)
Definition: vpMath.h:300
static void YUV422ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
static void YUV420ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
error that can be emited by ViSP classes.
Definition: vpException.h:71
static void YUV422ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
static void YCbCrToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void YUV411ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
static void split(const vpImage< vpRGBa > &src, vpImage< unsigned char > *pR, vpImage< unsigned char > *pG, vpImage< unsigned char > *pB, vpImage< unsigned char > *pa=NULL)
static void YUVToRGB(unsigned char y, unsigned char u, unsigned char v, unsigned char &r, unsigned char &g, unsigned char &b)
unsigned char G
Green component.
Definition: vpRGBa.h:149
static void GreyToRGB(unsigned char *grey, unsigned char *rgb, unsigned int size)
static void RGBToHSV(const unsigned char *rgb, double *hue, double *saturation, double *value, unsigned int size)
Definition: vpRGBa.h:66
static void YUV444ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
static void GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int width, unsigned int height)
static void YUV420ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YVU9ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YUV422ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false)
static void YVU9ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
static void YV12ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YCbCrToGrey(unsigned char *ycbcr, unsigned char *grey, unsigned int size)
unsigned int getCols() const
Definition: vpImage.h:179
unsigned char A
Additionnal component.
Definition: vpRGBa.h:151
static void YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
static void MONO16ToRGBa(unsigned char *grey16, unsigned char *rgba, unsigned int size)
static void RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void HSVToRGBa(const double *hue, const double *saturation, const double *value, unsigned char *rgba, unsigned int size)
static void merge(const vpImage< unsigned char > *R, const vpImage< unsigned char > *G, const vpImage< unsigned char > *B, const vpImage< unsigned char > *a, vpImage< vpRGBa > &RGBa)
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static int round(double x)
Definition: vpMath.h:245
static void YUYVToRGB(unsigned char *yuyv, unsigned char *rgb, unsigned int width, unsigned int height)
static void YUV444ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
static void YUV444ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
unsigned int getHeight() const
Definition: vpImage.h:188
static void YUV411ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
unsigned int getSize() const
Definition: vpImage.h:227
unsigned char R
Red component.
Definition: vpRGBa.h:148
#define vpDEBUG_TRACE
Definition: vpDebug.h:487
static void YCbCrToRGBa(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void YUV411ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
static void YCrCbToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void YCrCbToRGBa(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
unsigned int getWidth() const
Definition: vpImage.h:246
static void createDepthHistogram(const vpImage< uint16_t > &src_depth, vpImage< vpRGBa > &dest_rgba)
void getMinMaxValue(Type &min, Type &max) const
Look for the minimum and the maximum value within the bitmap.
Definition: vpImage.h:938
static void YV12ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
static void YUV420ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)