Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpImageConvert.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Convert image types.
32  *
33  * Authors:
34  * Eric Marchand
35  * Fabien Spindler
36  * Anthony Saunier
37  *
38  *****************************************************************************/
39 
46 #include <sstream>
47 #include <map>
48 
49 // image
50 #include <visp3/core/vpImageConvert.h>
51 
52 #if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2)
53 # include <emmintrin.h>
54 # define VISP_HAVE_SSE2 1
55 
56 # if defined __SSE3__ || (defined _MSC_VER && _MSC_VER >= 1500)
57 # include <pmmintrin.h>
58 # define VISP_HAVE_SSE3 1
59 # endif
60 # if defined __SSSE3__ || (defined _MSC_VER && _MSC_VER >= 1500)
61 # include <tmmintrin.h>
62 # define VISP_HAVE_SSSE3 1
63 # endif
64 #endif
65 
66 
67 bool vpImageConvert::YCbCrLUTcomputed = false;
68 int vpImageConvert::vpCrr[256];
69 int vpImageConvert::vpCgb[256];
70 int vpImageConvert::vpCgr[256];
71 int vpImageConvert::vpCbb[256];
72 
73 
80 void
82 {
83  dest.resize(src.getHeight(), src.getWidth()) ;
84 
85  GreyToRGBa(src.bitmap, (unsigned char *)dest.bitmap, src.getHeight() * src.getWidth() );
86 }
87 
93 void
95 {
96  dest.resize(src.getHeight(), src.getWidth()) ;
97 
98  RGBaToGrey((unsigned char *)src.bitmap, dest.bitmap, src.getHeight() * src.getWidth());
99 }
100 
101 
107 void
109 {
110  dest.resize(src.getHeight(), src.getWidth()) ;
111  unsigned int max_xy = src.getWidth()*src.getHeight();
112  float min, max;
113 
114  src.getMinMaxValue(min,max);
115 
116  for (unsigned int i = 0; i < max_xy; i++) {
117  float val = 255.f * (src.bitmap[i] - min) / (max - min);
118  if(val < 0)
119  dest.bitmap[i] = 0;
120  else if(val > 255)
121  dest.bitmap[i] = 255;
122  else
123  dest.bitmap[i] = (unsigned char)val;
124  }
125 }
126 
132 void
134 {
135  dest.resize(src.getHeight(), src.getWidth()) ;
136  for (unsigned int i = 0; i < src.getHeight()*src.getWidth(); i++)
137  dest.bitmap[i] = (float)src.bitmap[i];
138 }
139 
145 void
147 {
148  dest.resize(src.getHeight(), src.getWidth()) ;
149  unsigned int max_xy = src.getWidth()*src.getHeight();
150  double min, max;
151 
152  src.getMinMaxValue(min,max);
153 
154  for (unsigned int i = 0; i < max_xy; i++) {
155  double val = 255. * (src.bitmap[i] - min) / (max - min);
156  if(val < 0)
157  dest.bitmap[i] = 0;
158  else if(val > 255)
159  dest.bitmap[i] = 255;
160  else
161  dest.bitmap[i] = (unsigned char)val;
162  }
163 }
164 
170 void
172 {
173  dest.resize(src.getHeight(), src.getWidth()) ;
174 
175  for (unsigned int i=0; i< src.getSize(); i++)
176  dest.bitmap[i] = (src.bitmap[i] >> 8);
177 }
178 
184 void
186 {
187  dest.resize(src.getHeight(), src.getWidth()) ;
188 
189  for (unsigned int i=0; i< src.getSize(); i++)
190  dest.bitmap[i] = (src.bitmap[i] << 8);
191 }
192 
198 void
200 {
201  dest.resize(src.getHeight(), src.getWidth()) ;
202  for (unsigned int i = 0; i < src.getHeight()*src.getWidth(); i++)
203  dest.bitmap[i] = (double)src.bitmap[i];
204 }
205 
212 void
214 {
215  dest_rgba.resize(src_depth.getHeight(), src_depth.getWidth());
216  static uint32_t histogram[0x10000];
217  memset(histogram, 0, sizeof(histogram));
218  for(unsigned int i = 0; i < src_depth.getSize(); ++i) ++histogram[src_depth.bitmap[i]];
219  for(int i = 2; i < 0x10000; ++i) histogram[i] += histogram[i-1]; // Build a cumulative histogram for the indices in [1,0xFFFF]
220 
221  for(unsigned int i = 0; i < src_depth.getSize(); ++i)
222  {
223  uint16_t d = src_depth.bitmap[i];
224  if(d)
225  {
226  int f = (int)(histogram[d] * 255 / histogram[0xFFFF]); // 0-255 based on histogram location
227  dest_rgba.bitmap[i].R = 255 - f;
228  dest_rgba.bitmap[i].G = 0;
229  dest_rgba.bitmap[i].B = f;
230  dest_rgba.bitmap[i].A = vpRGBa::alpha_default;
231  }
232  else
233  {
234  dest_rgba.bitmap[i].R = 20;
235  dest_rgba.bitmap[i].G = 5;
236  dest_rgba.bitmap[i].B = 0;
237  dest_rgba.bitmap[i].A = vpRGBa::alpha_default;
238  }
239  }
240 }
241 
242 #ifdef VISP_HAVE_OPENCV
243 // Deprecated: will be removed with OpenCV transcient from C to C++ api
289 void
290 vpImageConvert::convert(const IplImage* src, vpImage<vpRGBa> & dest, bool flip)
291 {
292  int nChannel = src->nChannels;
293  int depth = src->depth;
294  int height = src->height;
295  int width = src->width;
296  int widthStep = src->widthStep;
297  int lineStep = (flip) ? 1 : 0;
298 
299  if(nChannel == 3 && depth == 8){
300  dest.resize((unsigned int)height, (unsigned int)width);
301 
302  //starting source address
303  unsigned char* input = (unsigned char*)src->imageData;
304  unsigned char* beginOutput = (unsigned char*)dest.bitmap;
305 
306  for(int i=0 ; i < height ; i++)
307  {
308  unsigned char *line = input;
309  unsigned char *output = beginOutput + lineStep * ( 4 * width * ( height - 1 - i ) ) + (1-lineStep) * 4 * width * i;
310  for(int j=0 ; j < width ; j++)
311  {
312  *(output++) = *(line+2);
313  *(output++) = *(line+1);
314  *(output++) = *(line);
315  *(output++) = vpRGBa::alpha_default;
316 
317  line+=3;
318  }
319  //go to the next line
320  input+=widthStep;
321  }
322  }
323  else if(nChannel == 1 && depth == 8 ){
324  dest.resize((unsigned int)height, (unsigned int)width);
325  //starting source address
326  unsigned char *input = (unsigned char*)src->imageData;
327  unsigned char *beginOutput = (unsigned char*)dest.bitmap;
328 
329  for(int i=0 ; i < height ; i++)
330  {
331  unsigned char *line = input;
332  unsigned char *output = beginOutput + lineStep * ( 4 * width * ( height - 1 - i ) ) + (1-lineStep) * 4 * width * i;
333  for(int j=0 ; j < width ; j++)
334  {
335  *output++ = *(line);
336  *output++ = *(line);
337  *output++ = *(line);
338  *output++ = vpRGBa::alpha_default; // alpha
339 
340  line++;
341  }
342  //go to the next line
343  input+=widthStep;
344  }
345  }
346 }
347 
391 void
392 vpImageConvert::convert(const IplImage* src, vpImage<unsigned char> &dest, bool flip)
393 {
394  int nChannel = src->nChannels;
395  int depth = src->depth;
396  int height = src->height;
397  int width = src->width;
398  int widthStep = src->widthStep;
399  int lineStep = (flip) ? 1 : 0;
400 
401  if (flip == false)
402  {
403  if(widthStep == width){
404  if(nChannel == 1 && depth == 8){
405  dest.resize((unsigned int)height, (unsigned int)width) ;
406  memcpy(dest.bitmap, src->imageData,
407  (size_t)(height*width));
408  }
409  if(nChannel == 3 && depth == 8){
410  dest.resize((unsigned int)height, (unsigned int)width) ;
411  BGRToGrey((unsigned char*)src->imageData,dest.bitmap, (unsigned int)width, (unsigned int)height,false);
412  }
413  }
414  else{
415  if(nChannel == 1 && depth == 8){
416  dest.resize((unsigned int)height, (unsigned int)width) ;
417  for (int i =0 ; i < height ; i++){
418  memcpy(dest.bitmap+i*width, src->imageData + i*widthStep,
419  (size_t)width);
420  }
421  }
422  if(nChannel == 3 && depth == 8){
423  dest.resize((unsigned int)height, (unsigned int)width) ;
424  for (int i = 0 ; i < height ; i++){
425  BGRToGrey((unsigned char*)src->imageData + i*widthStep,
426  dest.bitmap + i*width, (unsigned int)width, 1, false);
427  }
428  }
429  }
430  }
431  else
432  {
433  if(nChannel == 1 && depth == 8){
434  dest.resize((unsigned int)height, (unsigned int)width) ;
435  unsigned char* beginOutput = (unsigned char*)dest.bitmap;
436  for (int i =0 ; i < height ; i++){
437  memcpy(beginOutput + lineStep * ( 4 * width * ( height - 1 - i ) ) , src->imageData + i*widthStep,
438  (size_t)width);
439  }
440  }
441  if(nChannel == 3 && depth == 8){
442  dest.resize((unsigned int)height, (unsigned int)width) ;
443  //for (int i = 0 ; i < height ; i++){
444  BGRToGrey((unsigned char*)src->imageData /*+ i*widthStep*/,
445  dest.bitmap /*+ i*width*/, (unsigned int)width, (unsigned int)height/*1*/, true);
446  //}
447  }
448  }
449 }
450 
495 void
496 vpImageConvert::convert(const vpImage<vpRGBa> & src, IplImage *&dest)
497 {
498  int height = (int)src.getHeight();
499  int width = (int)src.getWidth();
500  CvSize size = cvSize(width, height);
501  int depth = 8;
502  int channels = 3;
503  if (dest != NULL){
504  if(dest->nChannels != channels || dest->depth != depth
505  || dest->height != height || dest->width != width){
506  if(dest->nChannels != 0) cvReleaseImage(&dest);
507  dest = cvCreateImage( size, depth, channels );
508  }
509  }
510  else dest = cvCreateImage( size, depth, channels );
511 
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  {
523  output = (unsigned char*)dest->imageData + i*widthStep;
524  unsigned char *line = input;
525  for( j=0 ; j < width ; j++)
526  {
527  *output++ = *(line+2); //B
528  *output++ = *(line+1); //G
529  *output++ = *(line); //R
530 
531  line+=4;
532  }
533  //go to the next line
534  input+=4*width;
535  }
536 }
537 
582 void
583 vpImageConvert::convert(const vpImage<unsigned char> & src, IplImage* &dest)
584 {
585  unsigned int height = src.getHeight();
586  unsigned int width = src.getWidth();
587  CvSize size = cvSize((int)width, (int)height);
588  int depth = 8;
589  int channels = 1;
590  if (dest != NULL){
591  if(dest->nChannels != channels || dest->depth != depth
592  || dest->height != (int) height || dest->width != (int) width){
593  if(dest->nChannels != 0) cvReleaseImage(&dest);
594  dest = cvCreateImage( size, depth, channels );
595  }
596  }
597  else dest = cvCreateImage( size, depth, channels );
598 
599  unsigned int widthStep = (unsigned int)dest->widthStep;
600 
601  if ( width == widthStep){
602  memcpy(dest->imageData,src.bitmap, width*height);
603  }
604  else{
605  //copying each line taking account of the widthStep
606  for (unsigned int i =0 ; i < height ; i++){
607  memcpy(dest->imageData + i*widthStep, src.bitmap + i*width,
608  width);
609  }
610  }
611 }
612 
613 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
614 
658 void
659 vpImageConvert::convert(const cv::Mat& src, vpImage<vpRGBa>& dest, const bool flip)
660 {
661  if(src.type() == CV_8UC4){
662  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
663  vpRGBa rgbaVal;
664  for(unsigned int i=0; i<dest.getRows(); ++i)
665  for(unsigned int j=0; j<dest.getCols(); ++j){
666  cv::Vec4b tmp = src.at<cv::Vec4b>((int)i, (int)j);
667  rgbaVal.R = tmp[2];
668  rgbaVal.G = tmp[1];
669  rgbaVal.B = tmp[0];
670  rgbaVal.A = tmp[3];
671  if(flip)
672  dest[dest.getRows()-i-1][j] = rgbaVal;
673  else
674  dest[i][j] = rgbaVal;
675  }
676  }else if(src.type() == CV_8UC3){
677  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
678  vpRGBa rgbaVal;
679  rgbaVal.A = vpRGBa::alpha_default;
680  for(unsigned int i=0; i<dest.getRows(); ++i){
681  for(unsigned int j=0; j<dest.getCols(); ++j){
682  cv::Vec3b tmp = src.at<cv::Vec3b>((int)i, (int)j);
683  rgbaVal.R = tmp[2];
684  rgbaVal.G = tmp[1];
685  rgbaVal.B = tmp[0];
686  if(flip){
687  dest[dest.getRows()-i-1][j] = rgbaVal;
688  }else{
689  dest[i][j] = rgbaVal;
690  }
691  }
692  }
693  }else if(src.type() == CV_8UC1){
694  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
695  vpRGBa rgbaVal;
696  for(unsigned int i=0; i<dest.getRows(); ++i){
697  for(unsigned int j=0; j<dest.getCols(); ++j){
698  rgbaVal = src.at<unsigned char>((int)i, (int)j);
699  if(flip){
700  dest[dest.getRows()-i-1][j] = rgbaVal;
701  }else{
702  dest[i][j] = rgbaVal;
703  }
704  }
705  }
706  }
707 }
708 
751 void
752 vpImageConvert::convert(const cv::Mat& src, vpImage<unsigned char>& dest, const bool flip)
753 {
754  if(src.type() == CV_8UC1){
755  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
756  if(src.isContinuous() && !flip){
757  memcpy(dest.bitmap, src.data, (size_t)(src.rows*src.cols));
758  }
759  else{
760  if(flip){
761  for(unsigned int i=0; i<dest.getRows(); ++i){
762  memcpy(dest.bitmap+i*dest.getCols(), src.data+(dest.getRows()-i-1)*src.step1(), (size_t)src.step);
763  }
764  }else{
765  for(unsigned int i=0; i<dest.getRows(); ++i){
766  memcpy(dest.bitmap+i*dest.getCols(), src.data+i*src.step1(), (size_t)src.step);
767  }
768  }
769  }
770  }else if(src.type() == CV_8UC3){
771  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
772  if(src.isContinuous() /*&& !flip*/){
773  BGRToGrey((unsigned char*)src.data, (unsigned char*)dest.bitmap, (unsigned int)src.cols, (unsigned int)src.rows, flip);
774  }
775  else{
776  if(flip){
777  for(unsigned int i=0; i<dest.getRows(); ++i){
778  BGRToGrey((unsigned char*)src.data+i*src.step1(),
779  (unsigned char*)dest.bitmap+(dest.getRows()-i-1)*dest.getCols(),
780  (unsigned int)dest.getCols(), 1, false);
781  }
782  }else{
783  for(unsigned int i=0; i<dest.getRows(); ++i){
784  BGRToGrey((unsigned char*)src.data+i*src.step1(),
785  (unsigned char*)dest.bitmap+i*dest.getCols(),
786  (unsigned int)dest.getCols(), 1, false);
787  }
788  }
789  }
790  }
791 }
792 
793 
833 void
834 vpImageConvert::convert(const vpImage<vpRGBa> & src, cv::Mat& dest)
835 {
836  cv::Mat vpToMat((int)src.getRows(), (int)src.getCols(), CV_8UC4, (void*)src.bitmap);
837 
838  dest = cv::Mat((int)src.getRows(), (int)src.getCols(), CV_8UC3);
839  cv::Mat alpha((int)src.getRows(), (int)src.getCols(), CV_8UC1);
840 
841  cv::Mat out[] = {dest, alpha};
842  int from_to[] = { 0,2, 1,1, 2,0, 3,3 };
843  cv::mixChannels(&vpToMat, 1, out, 2, from_to, 4);
844 }
845 
887 void
888 vpImageConvert::convert(const vpImage<unsigned char> & src, cv::Mat& dest, const bool copyData)
889 {
890  if(copyData){
891  cv::Mat tmpMap((int)src.getRows(), (int)src.getCols(), CV_8UC1, (void*)src.bitmap);
892  dest = tmpMap.clone();
893  }else{
894  dest = cv::Mat((int)src.getRows(), (int)src.getCols(), CV_8UC1, (void*)src.bitmap);
895  }
896 }
897 
898 #endif
899 #endif
900 
901 #ifdef VISP_HAVE_YARP
902 
935  yarp::sig::ImageOf< yarp::sig::PixelMono > *dest, const bool copyData)
936 {
937  if(copyData)
938  {
939  dest->resize(src.getWidth(),src.getHeight());
940  memcpy(dest->getRawImage(), src.bitmap, src.getHeight()*src.getWidth());
941  }
942  else
943  dest->setExternal(src.bitmap, (int)src.getCols(), (int)src.getRows());
944 }
945 
982 void vpImageConvert::convert(const yarp::sig::ImageOf< yarp::sig::PixelMono > *src,
983  vpImage<unsigned char> & dest,const bool copyData)
984 {
985  dest.resize(src->height(),src->width());
986  if(copyData)
987  memcpy(dest.bitmap, src->getRawImage(), src->height()*src->width()*sizeof(yarp::sig::PixelMono));
988  else
989  dest.bitmap = src->getRawImage();
990 }
991 
1026  yarp::sig::ImageOf< yarp::sig::PixelRgba > *dest, const bool copyData)
1027 {
1028  if(copyData){
1029  dest->resize(src.getWidth(),src.getHeight());
1030  memcpy(dest->getRawImage(), src.bitmap, src.getHeight()*src.getWidth()*sizeof(vpRGBa));
1031  }
1032  else
1033  dest->setExternal(src.bitmap, (int)src.getCols(), (int)src.getRows());
1034 }
1035 
1073 void vpImageConvert::convert(const yarp::sig::ImageOf< yarp::sig::PixelRgba > *src,
1074  vpImage<vpRGBa> & dest,const bool copyData)
1075 {
1076  dest.resize(src->height(),src->width());
1077  if(copyData)
1078  memcpy(dest.bitmap, src->getRawImage(),src->height()*src->width()*sizeof(yarp::sig::PixelRgba));
1079  else
1080  dest.bitmap = (vpRGBa*)src->getRawImage();
1081 }
1082 
1115 void vpImageConvert::convert(const vpImage<vpRGBa> & src, yarp::sig::ImageOf< yarp::sig::PixelRgb > *dest)
1116 {
1117  dest->resize(src.getWidth(),src.getHeight());
1118  for(unsigned int i = 0 ; i < src.getRows() ; i++){
1119  for(unsigned int j = 0 ; j < src.getWidth() ; j++){
1120  dest->pixel(j,i).r = src[i][j].R;
1121  dest->pixel(j,i).g = src[i][j].G;
1122  dest->pixel(j,i).b = src[i][j].B;
1123  }
1124  }
1125 }
1126 
1165 void vpImageConvert::convert(const yarp::sig::ImageOf< yarp::sig::PixelRgb > *src, vpImage<vpRGBa> & dest)
1166 {
1167  dest.resize(src->height(),src->width());
1168  for(int i = 0 ; i < src->height() ; i++){
1169  for(int j = 0 ; j < src->width() ; j++){
1170  dest[i][j].R = src->pixel(j,i).r;
1171  dest[i][j].G = src->pixel(j,i).g;
1172  dest[i][j].B = src->pixel(j,i).b;
1173  dest[i][j].A = vpRGBa::alpha_default;
1174  }
1175  }
1176 }
1177 
1178 #endif
1179 
1180 #define vpSAT(c) \
1181  if (c & (~255)) { if (c < 0) c = 0; else c = 255; }
1182 
1190 void vpImageConvert::YUYVToRGBa(unsigned char* yuyv, unsigned char* rgba,
1191  unsigned int width, unsigned int height)
1192 {
1193  unsigned char *s;
1194  unsigned char *d;
1195  int w, h;
1196  int r, g, b, cr, cg, cb, y1, y2;
1197 
1198  h = (int)height;
1199  w = (int)width;
1200  s = yuyv;
1201  d = rgba;
1202  while (h--) {
1203  int c = w >> 1;
1204  while (c--) {
1205  y1 = *s++;
1206  cb = ((*s - 128) * 454) >> 8;
1207  cg = (*s++ - 128) * 88;
1208  y2 = *s++;
1209  cr = ((*s - 128) * 359) >> 8;
1210  cg = (cg + (*s++ - 128) * 183) >> 8;
1211 
1212  r = y1 + cr;
1213  b = y1 + cb;
1214  g = y1 - cg;
1215  vpSAT(r);
1216  vpSAT(g);
1217  vpSAT(b);
1218 
1219  *d++ = static_cast<unsigned char>(r);
1220  *d++ = static_cast<unsigned char>(g);
1221  *d++ = static_cast<unsigned char>(b);
1222  *d++ = vpRGBa::alpha_default;
1223 
1224  r = y2 + cr;
1225  b = y2 + cb;
1226  g = y2 - cg;
1227  vpSAT(r);
1228  vpSAT(g);
1229  vpSAT(b);
1230 
1231  *d++ = static_cast<unsigned char>(r);
1232  *d++ = static_cast<unsigned char>(g);
1233  *d++ = static_cast<unsigned char>(b);
1234  *d++ = vpRGBa::alpha_default;
1235  }
1236  }
1237 }
1238 
1246 void vpImageConvert::YUYVToRGB(unsigned char* yuyv, unsigned char* rgb,
1247  unsigned int width, unsigned int height)
1248 {
1249  unsigned char *s;
1250  unsigned char *d;
1251  int h, w;
1252  int r, g, b, cr, cg, cb, y1, y2;
1253 
1254  h = (int)height;
1255  w = (int)width;
1256  s = yuyv;
1257  d = rgb;
1258  while (h--) {
1259  int c = w >> 1;
1260  while (c--) {
1261  y1 = *s++;
1262  cb = ((*s - 128) * 454) >> 8;
1263  cg = (*s++ - 128) * 88;
1264  y2 = *s++;
1265  cr = ((*s - 128) * 359) >> 8;
1266  cg = (cg + (*s++ - 128) * 183) >> 8;
1267 
1268  r = y1 + cr;
1269  b = y1 + cb;
1270  g = y1 - cg;
1271  vpSAT(r);
1272  vpSAT(g);
1273  vpSAT(b);
1274 
1275  *d++ = static_cast<unsigned char>(r);
1276  *d++ = static_cast<unsigned char>(g);
1277  *d++ = static_cast<unsigned char>(b);
1278 
1279  r = y2 + cr;
1280  b = y2 + cb;
1281  g = y2 - cg;
1282  vpSAT(r);
1283  vpSAT(g);
1284  vpSAT(b);
1285 
1286  *d++ = static_cast<unsigned char>(r);
1287  *d++ = static_cast<unsigned char>(g);
1288  *d++ = static_cast<unsigned char>(b);
1289  }
1290  }
1291 }
1299 void vpImageConvert::YUYVToGrey(unsigned char* yuyv, unsigned char* grey, unsigned int size)
1300 {
1301  unsigned int i=0,j=0;
1302 
1303  while( j < size*2)
1304  {
1305  grey[i++] = yuyv[j];
1306  grey[i++] = yuyv[j+2];
1307  j+=4;
1308  }
1309 }
1310 
1311 
1318 void vpImageConvert::YUV411ToRGBa(unsigned char* yuv, unsigned char* rgba, unsigned int size)
1319 {
1320 #if 1
1321  // std::cout << "call optimized ConvertYUV411ToRGBa()" << std::endl;
1322  for(unsigned int i = size / 4; i; i--) {
1323  int U = (int)((*yuv++ - 128) * 0.354);
1324  int U5 = 5*U;
1325  int Y0 = *yuv++;
1326  int Y1 = *yuv++;
1327  int V = (int)((*yuv++ - 128) * 0.707);
1328  int V2 = 2*V;
1329  int Y2 = *yuv++;
1330  int Y3 = *yuv++;
1331  int UV = - U - V;
1332 
1333  // Original equations
1334  // R = Y + 1.402 V
1335  // G = Y - 0.344 U - 0.714 V
1336  // B = Y + 1.772 U
1337  int R = Y0 + V2;
1338  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1339 
1340  int G = Y0 + UV;
1341  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1342 
1343  int B = Y0 + U5;
1344  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1345 
1346  *rgba++ = (unsigned char)R;
1347  *rgba++ = (unsigned char)G;
1348  *rgba++ = (unsigned char)B;
1349  *rgba++ = vpRGBa::alpha_default;
1350 
1351  //---
1352  R = Y1 + V2;
1353  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1354 
1355  G = Y1 + UV;
1356  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1357 
1358  B = Y1 + U5;
1359  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1360 
1361  *rgba++ = (unsigned char)R;
1362  *rgba++ = (unsigned char)G;
1363  *rgba++ = (unsigned char)B;
1364  *rgba++ = vpRGBa::alpha_default;
1365 
1366  //---
1367  R = Y2 + V2;
1368  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1369 
1370  G = Y2 + UV;
1371  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1372 
1373  B = Y2 + U5;
1374  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1375 
1376  *rgba++ = (unsigned char)R;
1377  *rgba++ = (unsigned char)G;
1378  *rgba++ = (unsigned char)B;
1379  *rgba++ = vpRGBa::alpha_default;
1380 
1381  //---
1382  R = Y3 + V2;
1383  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1384 
1385  G = Y3 + UV;
1386  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1387 
1388  B = Y3 + U5;
1389  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1390 
1391  *rgba++ = (unsigned char)R;
1392  *rgba++ = (unsigned char)G;
1393  *rgba++ = (unsigned char)B;
1394  *rgba++ = vpRGBa::alpha_default;
1395  }
1396 #else
1397  // tres tres lent ....
1398  unsigned int i=0,j=0;
1399  unsigned char r, g, b;
1400  while( j < numpixels*3/2)
1401  {
1402 
1403  YUVToRGB (yuv[j+1], yuv[j], yuv[j+3], r, g, b);
1404  rgba[i] = r;
1405  rgba[i+1] = g;
1406  rgba[i+2] = b;
1407  rgba[i+3] = vpRGBa::alpha_default;
1408  i+=4;
1409 
1410  YUVToRGB (yuv[j+2], yuv[j], yuv[j+3], r, g, b);
1411  rgba[i] = r;
1412  rgba[i+1] = g;
1413  rgba[i+2] = b;
1414  rgba[i+3] = vpRGBa::alpha_default;
1415  i+=4;
1416 
1417  YUVToRGB (yuv[j+4], yuv[j], yuv[j+3], r, g, b);
1418  rgba[i] = r;
1419  rgba[i+1] = g;
1420  rgba[i+2] = b;
1421  rgba[i+3] = vpRGBa::alpha_default;
1422  i+=4;
1423 
1424  YUVToRGB (yuv[j+5], yuv[j], yuv[j+3], r, g, b);
1425  rgba[i] = r;
1426  rgba[i+1] = g;
1427  rgba[i+2] = b;
1428  rgba[i+3] = vpRGBa::alpha_default;
1429  i+=4;
1430 
1431  j+=6;
1432  }
1433 #endif
1434 
1435 }
1436 
1445 void vpImageConvert::YUV422ToRGBa(unsigned char* yuv, unsigned char* rgba, unsigned int size)
1446 {
1447 
1448 #if 1
1449  // std::cout << "call optimized convertYUV422ToRGBa()" << std::endl;
1450  for( unsigned int i = size / 2; i; i-- ) {
1451  int U = (int)((*yuv++ - 128) * 0.354);
1452  int U5 = 5*U;
1453  int Y0 = *yuv++;
1454  int V = (int)((*yuv++ - 128) * 0.707);
1455  int V2 = 2*V;
1456  int Y1 = *yuv++;
1457  int UV = - U - V;
1458 
1459  //---
1460  int R = Y0 + V2;
1461  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1462 
1463  int G = Y0 + UV;
1464  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1465 
1466  int B = Y0 + U5;
1467  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1468 
1469  *rgba++ = (unsigned char)R;
1470  *rgba++ = (unsigned char)G;
1471  *rgba++ = (unsigned char)B;
1472  *rgba++ = vpRGBa::alpha_default;
1473 
1474  //---
1475  R = Y1 + V2;
1476  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1477 
1478  G = Y1 + UV;
1479  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1480 
1481  B = Y1 + U5;
1482  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1483 
1484  *rgba++ = (unsigned char)R;
1485  *rgba++ = (unsigned char)G;
1486  *rgba++ = (unsigned char)B;
1487  *rgba++ = vpRGBa::alpha_default;
1488  }
1489 
1490 #else
1491  // tres tres lent ....
1492  unsigned int i=0,j=0;
1493  unsigned char r, g, b;
1494 
1495  while( j < size*2)
1496  {
1497 
1498  YUVToRGB (yuv[j+1], yuv[j], yuv[j+2], r, g, b);
1499  rgba[i] = r;
1500  rgba[i+1] = g;
1501  rgba[i+2] = b;
1502  rgba[i+3] = vpRGBa::alpha_default;
1503  i+=4;
1504 
1505  YUVToRGB (yuv[j+3], yuv[j], yuv[j+2], r, g, b);
1506  rgba[i] = r;
1507  rgba[i+1] = g;
1508  rgba[i+2] = b;
1509  rgba[i+3] = vpRGBa::alpha_default;
1510  i+=4;
1511  j+=4;
1512 
1513  }
1514 #endif
1515 }
1516 
1523 void vpImageConvert::YUV411ToGrey(unsigned char* yuv, unsigned char* grey, unsigned int size)
1524 {
1525  unsigned int i=0,j=0;
1526  while( j < size*3/2)
1527  {
1528  grey[i ] = yuv[j+1];
1529  grey[i+1] = yuv[j+2];
1530  grey[i+2] = yuv[j+4];
1531  grey[i+3] = yuv[j+5];
1532 
1533  i+=4;
1534 
1535  j+=6;
1536  }
1537 }
1538 
1547 void vpImageConvert::YUV422ToRGB(unsigned char* yuv, unsigned char* rgb, unsigned int size)
1548 {
1549 #if 1
1550  // std::cout << "call optimized convertYUV422ToRGB()" << std::endl;
1551  for( unsigned int i = size / 2; i; i-- ) {
1552  int U = (int)((*yuv++ - 128) * 0.354);
1553  int U5 = 5*U;
1554  int Y0 = *yuv++;
1555  int V = (int)((*yuv++ - 128) * 0.707);
1556  int V2 = 2*V;
1557  int Y1 = *yuv++;
1558  int UV = - U - V;
1559 
1560  //---
1561  int R = Y0 + V2;
1562  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1563 
1564  int G = Y0 + UV;
1565  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1566 
1567  int B = Y0 + U5;
1568  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1569 
1570  *rgb++ = (unsigned char)R;
1571  *rgb++ = (unsigned char)G;
1572  *rgb++ = (unsigned char)B;
1573 
1574  //---
1575  R = Y1 + V2;
1576  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1577 
1578  G = Y1 + UV;
1579  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1580 
1581  B = Y1 + U5;
1582  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1583 
1584  *rgb++ = (unsigned char)R;
1585  *rgb++ = (unsigned char)G;
1586  *rgb++ = (unsigned char)B;
1587 
1588  }
1589 
1590 #else
1591  // tres tres lent ....
1592  unsigned int i=0,j=0;
1593  unsigned char r, g, b;
1594 
1595  while( j < size*2)
1596  {
1597 
1598  YUVToRGB (yuv[j+1], yuv[j], yuv[j+2], r, g, b);
1599  rgb[i] = r;
1600  rgb[i+1] = g;
1601  rgb[i+2] = b;
1602  i+=3;
1603 
1604  YUVToRGB (yuv[j+3], yuv[j], yuv[j+2], r, g, b);
1605  rgb[i] = r;
1606  rgb[i+1] = g;
1607  rgb[i+2] = b;
1608  i+=3;
1609  j+=4;
1610 
1611  }
1612 #endif
1613 }
1614 
1623 void vpImageConvert::YUV422ToGrey(unsigned char* yuv, unsigned char* grey, unsigned int size)
1624 {
1625  unsigned int i=0,j=0;
1626 
1627  while( j < size*2)
1628  {
1629  grey[i++] = yuv[j+1];
1630  grey[i++] = yuv[j+3];
1631  j+=4;
1632  }
1633 }
1634 
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 = (int)((*yuv++ - 128) * 0.354);
1647  int U5 = 5*U;
1648  int Y0 = *yuv++;
1649  int Y1 = *yuv++;
1650  int V = (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) R = 255; else if (R < 0) R = 0;
1662 
1663  int G = Y0 + UV;
1664  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1665 
1666  int B = Y0 + U5;
1667  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1668 
1669  *rgb++ = (unsigned char)R;
1670  *rgb++ = (unsigned char)G;
1671  *rgb++ = (unsigned char)B;
1672 
1673  //---
1674  R = Y1 + V2;
1675  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1676 
1677  G = Y1 + UV;
1678  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1679 
1680  B = Y1 + U5;
1681  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1682 
1683  *rgb++ = (unsigned char)R;
1684  *rgb++ = (unsigned char)G;
1685  *rgb++ = (unsigned char)B;
1686 
1687  //---
1688  R = Y2 + V2;
1689  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1690 
1691  G = Y2 + UV;
1692  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1693 
1694  B = Y2 + U5;
1695  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1696 
1697  *rgb++ = (unsigned char)R;
1698  *rgb++ = (unsigned char)G;
1699  *rgb++ = (unsigned char)B;
1700 
1701  //---
1702  R = Y3 + V2;
1703  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1704 
1705  G = Y3 + UV;
1706  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1707 
1708  B = Y3 + U5;
1709  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1710 
1711  *rgb++ = (unsigned char)R;
1712  *rgb++ = (unsigned char)G;
1713  *rgb++ = (unsigned char)B;
1714  }
1715 #else
1716  // tres tres lent ....
1717 
1718  unsigned int i=0,j=0;
1719  unsigned char r, g, b;
1720 
1721  while( j < size*3/2)
1722  {
1723  YUVToRGB (yuv[j+1], yuv[j], yuv[j+3], r, g, b);
1724  rgb[i] = r;
1725  rgb[i+1] = g;
1726  rgb[i+2] = b;
1727  i+=3;
1728 
1729  YUVToRGB (yuv[j+2], yuv[j], yuv[j+3], r, g, b);
1730  rgb[i] = r;
1731  rgb[i+1] = g;
1732  rgb[i+2] = b;
1733  i+=3;
1734 
1735  YUVToRGB (yuv[j+4], yuv[j], yuv[j+3], r, g, b);
1736  rgb[i] = r;
1737  rgb[i+1] = g;
1738  rgb[i+2] = b;
1739  i+=3;
1740 
1741  YUVToRGB (yuv[j+5], yuv[j], yuv[j+3], r, g, b);
1742  rgb[i] = r;
1743  rgb[i+1] = g;
1744  rgb[i+2] = b;
1745  i+=3;
1746  //TRACE("r= %d g=%d b=%d", r, g, b);
1747 
1748  j+=6;
1749  }
1750 #endif
1751 
1752 }
1753 
1754 
1755 
1763 void vpImageConvert::YUV420ToRGBa(unsigned char* yuv, unsigned char* rgba,
1764  unsigned int width, unsigned int height)
1765 {
1766  // std::cout << "call optimized ConvertYUV420ToRGBa()" << std::endl;
1767  int U, V, R, G, B, V2, U5, UV;
1768  int Y0, Y1, Y2, Y3;
1769  unsigned int size = width*height;
1770  unsigned char* iU = yuv + size;
1771  unsigned char* iV = yuv + 5*size/4;
1772  for(unsigned int i = 0; i<height/2; i++)
1773  {
1774  for(unsigned int j = 0; j < width/2 ; j++)
1775  {
1776  U = (int)((*iU++ - 128) * 0.354);
1777  U5 = 5*U;
1778  V = (int)((*iV++ - 128) * 0.707);
1779  V2 = 2*V;
1780  UV = - U - V;
1781  Y0 = *yuv++;
1782  Y1 = *yuv;
1783  yuv = yuv+width-1;
1784  Y2 = *yuv++;
1785  Y3 = *yuv;
1786  yuv = yuv-width+1;
1787 
1788  // Original equations
1789  // R = Y + 1.402 V
1790  // G = Y - 0.344 U - 0.714 V
1791  // B = Y + 1.772 U
1792  R = Y0 + V2;
1793  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1794 
1795  G = Y0 + UV;
1796  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1797 
1798  B = Y0 + U5;
1799  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1800 
1801  *rgba++ = (unsigned char)R;
1802  *rgba++ = (unsigned char)G;
1803  *rgba++ = (unsigned char)B;
1804  *rgba++ = vpRGBa::alpha_default;
1805 
1806  //---
1807  R = Y1 + V2;
1808  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1809 
1810  G = Y1 + UV;
1811  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1812 
1813  B = Y1 + U5;
1814  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1815 
1816  *rgba++ = (unsigned char)R;
1817  *rgba++ = (unsigned char)G;
1818  *rgba++ = (unsigned char)B;
1819  *rgba = vpRGBa::alpha_default;
1820  rgba = rgba + 4*width-7;
1821 
1822  //---
1823  R = Y2 + V2;
1824  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1825 
1826  G = Y2 + UV;
1827  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1828 
1829  B = Y2 + U5;
1830  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1831 
1832  *rgba++ = (unsigned char)R;
1833  *rgba++ = (unsigned char)G;
1834  *rgba++ = (unsigned char)B;
1835  *rgba++ = vpRGBa::alpha_default;
1836 
1837  //---
1838  R = Y3 + V2;
1839  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1840 
1841  G = Y3 + UV;
1842  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1843 
1844  B = Y3 + U5;
1845  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1846 
1847  *rgba++ = (unsigned char)R;
1848  *rgba++ = (unsigned char)G;
1849  *rgba++ = (unsigned char)B;
1850  *rgba = vpRGBa::alpha_default;
1851  rgba = rgba -4*width+1;
1852  }
1853  yuv+=width;
1854  rgba+=4*width;
1855  }
1856 }
1862 void vpImageConvert::YUV420ToRGB(unsigned char* yuv,
1863  unsigned char* rgb,
1864  unsigned int width, unsigned int height)
1865 {
1866  // std::cout << "call optimized ConvertYUV420ToRGB()" << std::endl;
1867  int U, V, R, G, B, V2, U5, UV;
1868  int Y0, Y1, Y2, Y3;
1869  unsigned int size = width*height;
1870  unsigned char* iU = yuv + size;
1871  unsigned char* iV = yuv + 5*size/4;
1872  for(unsigned int i = 0; i<height/2; i++)
1873  {
1874  for(unsigned int j = 0; j < width/2 ; j++)
1875  {
1876  U = (int)((*iU++ - 128) * 0.354);
1877  U5 = 5*U;
1878  V = (int)((*iV++ - 128) * 0.707);
1879  V2 = 2*V;
1880  UV = - U - V;
1881  Y0 = *yuv++;
1882  Y1 = *yuv;
1883  yuv = yuv+width-1;
1884  Y2 = *yuv++;
1885  Y3 = *yuv;
1886  yuv = yuv-width+1;
1887 
1888  // Original equations
1889  // R = Y + 1.402 V
1890  // G = Y - 0.344 U - 0.714 V
1891  // B = Y + 1.772 U
1892  R = Y0 + V2;
1893  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1894 
1895  G = Y0 + UV;
1896  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1897 
1898  B = Y0 + U5;
1899  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1900 
1901  *rgb++ = (unsigned char)R;
1902  *rgb++ = (unsigned char)G;
1903  *rgb++ = (unsigned char)B;
1904 
1905  //---
1906  R = Y1 + V2;
1907  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1908 
1909  G = Y1 + UV;
1910  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1911 
1912  B = Y1 + U5;
1913  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1914 
1915  *rgb++ = (unsigned char)R;
1916  *rgb++ = (unsigned char)G;
1917  *rgb = (unsigned char)B;
1918  rgb = rgb + 3*width-5;
1919 
1920  //---
1921  R = Y2 + V2;
1922  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1923 
1924  G = Y2 + UV;
1925  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1926 
1927  B = Y2 + U5;
1928  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1929 
1930  *rgb++ = (unsigned char)R;
1931  *rgb++ = (unsigned char)G;
1932  *rgb++ = (unsigned char)B;
1933 
1934  //---
1935  R = Y3 + V2;
1936  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1937 
1938  G = Y3 + UV;
1939  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1940 
1941  B = Y3 + U5;
1942  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1943 
1944  *rgb++ = (unsigned char)R;
1945  *rgb++ = (unsigned char)G;
1946  *rgb = (unsigned char)B;
1947  rgb = rgb -3*width+1;
1948  }
1949  yuv+=width;
1950  rgb+=3*width;
1951  }
1952 }
1953 
1959 void vpImageConvert::YUV420ToGrey(unsigned char* yuv, unsigned char* grey, unsigned int size)
1960 {
1961  for(unsigned int i=0 ; i < size ; i++)
1962  {
1963  *grey++ = *yuv++;
1964  }
1965 }
1973 void vpImageConvert::YUV444ToRGBa(unsigned char* yuv, unsigned char* rgba, unsigned int size)
1974 {
1975  for(unsigned int i = 0; i<size; i++)
1976  {
1977  int U = (int)((*yuv++ - 128) * 0.354);
1978  int U5 = 5*U;
1979  int Y = *yuv++;
1980  int V = (int)((*yuv++ - 128) * 0.707);
1981  int V2 = 2*V;
1982  int UV = - U - V;
1983 
1984  // Original equations
1985  // R = Y + 1.402 V
1986  // G = Y - 0.344 U - 0.714 V
1987  // B = Y + 1.772 U
1988  int R = Y + V2;
1989  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
1990 
1991  int G = Y + UV;
1992  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
1993 
1994  int B = Y + U5;
1995  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
1996 
1997  *rgba++ = (unsigned char)R;
1998  *rgba++ = (unsigned char)G;
1999  *rgba++ = (unsigned char)B;
2000  *rgba++ = vpRGBa::alpha_default;
2001  }
2002 }
2008 void vpImageConvert::YUV444ToRGB(unsigned char* yuv, unsigned char* rgb, unsigned int size)
2009 {
2010  for(unsigned int i = 0; i<size; i++)
2011  {
2012  int U = (int)((*yuv++ - 128) * 0.354);
2013  int U5 = 5*U;
2014  int Y = *yuv++;
2015  int V = (int)((*yuv++ - 128) * 0.707);
2016  int V2 = 2*V;
2017  int UV = - U - V;
2018 
2019  // Original equations
2020  // R = Y + 1.402 V
2021  // G = Y - 0.344 U - 0.714 V
2022  // B = Y + 1.772 U
2023  int R = Y + V2;
2024  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2025 
2026  int G = Y + UV;
2027  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2028 
2029  int B = Y + U5;
2030  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2031 
2032  *rgb++ = (unsigned char)R;
2033  *rgb++ = (unsigned char)G;
2034  *rgb++ = (unsigned char)B;
2035  }
2036 }
2037 
2043 void vpImageConvert::YUV444ToGrey(unsigned char* yuv, unsigned char* grey, unsigned int size)
2044 {
2045  yuv++;
2046  for(unsigned int i=0 ; i < size ; i++)
2047  {
2048  *grey++ = *yuv;
2049  yuv = yuv + 3;
2050  }
2051 }
2052 
2060 void vpImageConvert::YV12ToRGBa(unsigned char* yuv, unsigned char* rgba,
2061  unsigned int width, unsigned int height)
2062 {
2063  // std::cout << "call optimized ConvertYV12ToRGBa()" << std::endl;
2064  int U, V, R, G, B, V2, U5, UV;
2065  int Y0, Y1, Y2, Y3;
2066  unsigned int size = width*height;
2067  unsigned char* iV = yuv + size;
2068  unsigned char* iU = yuv + 5*size/4;
2069  for(unsigned int i = 0; i<height/2; i++)
2070  {
2071  for(unsigned int j = 0; j < width/2 ; j++)
2072  {
2073  U = (int)((*iU++ - 128) * 0.354);
2074  U5 = 5*U;
2075  V = (int)((*iV++ - 128) * 0.707);
2076  V2 = 2*V;
2077  UV = - U - V;
2078  Y0 = *yuv++;
2079  Y1 = *yuv;
2080  yuv = yuv+width-1;
2081  Y2 = *yuv++;
2082  Y3 = *yuv;
2083  yuv = yuv-width+1;
2084 
2085  // Original equations
2086  // R = Y + 1.402 V
2087  // G = Y - 0.344 U - 0.714 V
2088  // B = Y + 1.772 U
2089  R = Y0 + V2;
2090  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2091 
2092  G = Y0 + UV;
2093  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2094 
2095  B = Y0 + U5;
2096  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2097 
2098  *rgba++ = (unsigned char)R;
2099  *rgba++ = (unsigned char)G;
2100  *rgba++ = (unsigned char)B;
2101  *rgba++ = vpRGBa::alpha_default;
2102 
2103  //---
2104  R = Y1 + V2;
2105  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2106 
2107  G = Y1 + UV;
2108  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2109 
2110  B = Y1 + U5;
2111  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2112 
2113  *rgba++ = (unsigned char)R;
2114  *rgba++ = (unsigned char)G;
2115  *rgba++ = (unsigned char)B;
2116  *rgba = 0;
2117  rgba = rgba + 4*width-7;
2118 
2119  //---
2120  R = Y2 + V2;
2121  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2122 
2123  G = Y2 + UV;
2124  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2125 
2126  B = Y2 + U5;
2127  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2128 
2129  *rgba++ = (unsigned char)R;
2130  *rgba++ = (unsigned char)G;
2131  *rgba++ = (unsigned char)B;
2132  *rgba++ = vpRGBa::alpha_default;
2133 
2134  //---
2135  R = Y3 + V2;
2136  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2137 
2138  G = Y3 + UV;
2139  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2140 
2141  B = Y3 + U5;
2142  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2143 
2144  *rgba++ = (unsigned char)R;
2145  *rgba++ = (unsigned char)G;
2146  *rgba++ = (unsigned char)B;
2147  *rgba = vpRGBa::alpha_default;
2148  rgba = rgba -4*width+1;
2149  }
2150  yuv+=width;
2151  rgba+=4*width;
2152  }
2153 }
2159 void vpImageConvert::YV12ToRGB(unsigned char* yuv, unsigned char* rgb,
2160  unsigned int height, unsigned int width)
2161 {
2162  // std::cout << "call optimized ConvertYV12ToRGB()" << std::endl;
2163  int U, V, R, G, B, V2, U5, UV;
2164  int Y0, Y1, Y2, Y3;
2165  unsigned int size = width*height;
2166  unsigned char* iV = yuv + size;
2167  unsigned char* iU = yuv + 5*size/4;
2168  for(unsigned int i = 0; i<height/2; i++)
2169  {
2170  for(unsigned int j = 0; j < width/2 ; j++)
2171  {
2172  U = (int)((*iU++ - 128) * 0.354);
2173  U5 = 5*U;
2174  V = (int)((*iV++ - 128) * 0.707);
2175  V2 = 2*V;
2176  UV = - U - V;
2177  Y0 = *yuv++;
2178  Y1 = *yuv;
2179  yuv = yuv+width-1;
2180  Y2 = *yuv++;
2181  Y3 = *yuv;
2182  yuv = yuv-width+1;
2183 
2184  // Original equations
2185  // R = Y + 1.402 V
2186  // G = Y - 0.344 U - 0.714 V
2187  // B = Y + 1.772 U
2188  R = Y0 + V2;
2189  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2190 
2191  G = Y0 + UV;
2192  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2193 
2194  B = Y0 + U5;
2195  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2196 
2197  *rgb++ = (unsigned char)R;
2198  *rgb++ = (unsigned char)G;
2199  *rgb++ = (unsigned char)B;
2200 
2201  //---
2202  R = Y1 + V2;
2203  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2204 
2205  G = Y1 + UV;
2206  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2207 
2208  B = Y1 + U5;
2209  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2210 
2211  *rgb++ = (unsigned char)R;
2212  *rgb++ = (unsigned char)G;
2213  *rgb = (unsigned char)B;
2214  rgb = rgb + 3*width-5;
2215 
2216  //---
2217  R = Y2 + V2;
2218  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2219 
2220  G = Y2 + UV;
2221  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2222 
2223  B = Y2 + U5;
2224  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2225 
2226  *rgb++ = (unsigned char)R;
2227  *rgb++ = (unsigned char)G;
2228  *rgb++ = (unsigned char)B;
2229 
2230  //---
2231  R = Y3 + V2;
2232  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2233 
2234  G = Y3 + UV;
2235  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2236 
2237  B = Y3 + U5;
2238  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2239 
2240  *rgb++ = (unsigned char)R;
2241  *rgb++ = (unsigned char)G;
2242  *rgb = (unsigned char)B;
2243  rgb = rgb -3*width+1;
2244  }
2245  yuv+=width;
2246  rgb+=3*width;
2247  }
2248 }
2249 
2257 void vpImageConvert::YVU9ToRGBa(unsigned char* yuv, unsigned char* rgba,
2258  unsigned int width, unsigned int height)
2259 {
2260  // std::cout << "call optimized ConvertYVU9ToRGBa()" << std::endl;
2261  int U, V, R, G, B, V2, U5, UV;
2262  int Y0, Y1, Y2, Y3,Y4, Y5, Y6, Y7,Y8, Y9, Y10, Y11,Y12, Y13, Y14, Y15;
2263  unsigned int size = width*height;
2264  unsigned char* iV = yuv + size;
2265  unsigned char* iU = yuv + 17*size/16;
2266  for(unsigned int i = 0; i<height/4; i++)
2267  {
2268  for(unsigned int j = 0; j < width/4 ; j++)
2269  {
2270  U = (int)((*iU++ - 128) * 0.354);
2271  U5 = 5*U;
2272  V = (int)((*iV++ - 128) * 0.707);
2273  V2 = 2*V;
2274  UV = - U - V;
2275  Y0 = *yuv++;
2276  Y1 = *yuv++;
2277  Y2 = *yuv++;
2278  Y3 = *yuv;
2279  yuv = yuv+width-3;
2280  Y4 = *yuv++;
2281  Y5 = *yuv++;
2282  Y6 = *yuv++;
2283  Y7 = *yuv;
2284  yuv = yuv+width-3;
2285  Y8 = *yuv++;
2286  Y9 = *yuv++;
2287  Y10 = *yuv++;
2288  Y11 = *yuv;
2289  yuv = yuv+width-3;
2290  Y12 = *yuv++;
2291  Y13 = *yuv++;
2292  Y14 = *yuv++;
2293  Y15 = *yuv;
2294  yuv = yuv-3*width+1;
2295 
2296  // Original equations
2297  // R = Y + 1.402 V
2298  // G = Y - 0.344 U - 0.714 V
2299  // B = Y + 1.772 U
2300  R = Y0 + V2;
2301  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2302 
2303  G = Y0 + UV;
2304  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2305 
2306  B = Y0 + U5;
2307  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2308 
2309  *rgba++ = (unsigned char)R;
2310  *rgba++ = (unsigned char)G;
2311  *rgba++ = (unsigned char)B;
2312  *rgba++ = vpRGBa::alpha_default;
2313 
2314  //---
2315  R = Y1 + V2;
2316  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2317 
2318  G = Y1 + UV;
2319  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2320 
2321  B = Y1 + U5;
2322  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2323 
2324  *rgba++ = (unsigned char)R;
2325  *rgba++ = (unsigned char)G;
2326  *rgba++ = (unsigned char)B;
2327  *rgba++ = vpRGBa::alpha_default;
2328 
2329  //---
2330  R = Y2 + V2;
2331  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2332 
2333  G = Y2 + UV;
2334  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2335 
2336  B = Y2 + U5;
2337  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2338 
2339  *rgba++ = (unsigned char)R;
2340  *rgba++ = (unsigned char)G;
2341  *rgba++ = (unsigned char)B;
2342  *rgba++ = vpRGBa::alpha_default;
2343 
2344  //---
2345  R = Y3 + V2;
2346  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2347 
2348  G = Y3 + UV;
2349  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2350 
2351  B = Y3 + U5;
2352  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2353 
2354  *rgba++ = (unsigned char)R;
2355  *rgba++ = (unsigned char)G;
2356  *rgba++ = (unsigned char)B;
2357  *rgba = vpRGBa::alpha_default;
2358  rgba = rgba + 4*width-15;
2359 
2360  R = Y4 + V2;
2361  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2362 
2363  G = Y4 + UV;
2364  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2365 
2366  B = Y4 + U5;
2367  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2368 
2369  *rgba++ = (unsigned char)R;
2370  *rgba++ = (unsigned char)G;
2371  *rgba++ = (unsigned char)B;
2372  *rgba++ = vpRGBa::alpha_default;
2373 
2374  //---
2375  R = Y5 + V2;
2376  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2377 
2378  G = Y5 + UV;
2379  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2380 
2381  B = Y5 + U5;
2382  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2383 
2384  *rgba++ = (unsigned char)R;
2385  *rgba++ = (unsigned char)G;
2386  *rgba++ = (unsigned char)B;
2387  *rgba++ = vpRGBa::alpha_default;
2388 
2389  //---
2390  R = Y6 + V2;
2391  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2392 
2393  G = Y6 + UV;
2394  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2395 
2396  B = Y6 + U5;
2397  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2398 
2399  *rgba++ = (unsigned char)R;
2400  *rgba++ = (unsigned char)G;
2401  *rgba++ = (unsigned char)B;
2402  *rgba++ = vpRGBa::alpha_default;
2403 
2404  //---
2405  R = Y7 + V2;
2406  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2407 
2408  G = Y7 + UV;
2409  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2410 
2411  B = Y7 + U5;
2412  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2413 
2414  *rgba++ = (unsigned char)R;
2415  *rgba++ = (unsigned char)G;
2416  *rgba++ = (unsigned char)B;
2417  *rgba = vpRGBa::alpha_default;
2418  rgba = rgba + 4*width-15;
2419 
2420  R = Y8 + V2;
2421  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2422 
2423  G = Y8 + UV;
2424  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2425 
2426  B = Y8 + U5;
2427  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2428 
2429  *rgba++ = (unsigned char)R;
2430  *rgba++ = (unsigned char)G;
2431  *rgba++ = (unsigned char)B;
2432  *rgba++ = vpRGBa::alpha_default;
2433 
2434  //---
2435  R = Y9 + V2;
2436  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2437 
2438  G = Y9 + UV;
2439  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2440 
2441  B = Y9 + U5;
2442  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2443 
2444  *rgba++ = (unsigned char)R;
2445  *rgba++ = (unsigned char)G;
2446  *rgba++ = (unsigned char)B;
2447  *rgba++ = vpRGBa::alpha_default;
2448 
2449  //---
2450  R = Y10 + V2;
2451  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2452 
2453  G = Y10 + UV;
2454  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2455 
2456  B = Y10 + U5;
2457  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2458 
2459  *rgba++ = (unsigned char)R;
2460  *rgba++ = (unsigned char)G;
2461  *rgba++ = (unsigned char)B;
2462  *rgba++ = vpRGBa::alpha_default;
2463 
2464  //---
2465  R = Y11 + V2;
2466  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2467 
2468  G = Y11 + UV;
2469  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2470 
2471  B = Y11 + U5;
2472  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2473 
2474  *rgba++ = (unsigned char)R;
2475  *rgba++ = (unsigned char)G;
2476  *rgba++ = (unsigned char)B;
2477  *rgba = vpRGBa::alpha_default;
2478  rgba = rgba + 4*width-15;
2479 
2480  R = Y12 + V2;
2481  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2482 
2483  G = Y12 + UV;
2484  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2485 
2486  B = Y12 + U5;
2487  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2488 
2489  *rgba++ = (unsigned char)R;
2490  *rgba++ = (unsigned char)G;
2491  *rgba++ = (unsigned char)B;
2492  *rgba++ = vpRGBa::alpha_default;
2493 
2494  //---
2495  R = Y13 + V2;
2496  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2497 
2498  G = Y13 + UV;
2499  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2500 
2501  B = Y13 + U5;
2502  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2503 
2504  *rgba++ = (unsigned char)R;
2505  *rgba++ = (unsigned char)G;
2506  *rgba++ = (unsigned char)B;
2507  *rgba++ = vpRGBa::alpha_default;
2508 
2509  //---
2510  R = Y14 + V2;
2511  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2512 
2513  G = Y14 + UV;
2514  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2515 
2516  B = Y14 + U5;
2517  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2518 
2519  *rgba++ = (unsigned char)R;
2520  *rgba++ = (unsigned char)G;
2521  *rgba++ = (unsigned char)B;
2522  *rgba++ = vpRGBa::alpha_default;
2523 
2524  //---
2525  R = Y15 + V2;
2526  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2527 
2528  G = Y15 + UV;
2529  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2530 
2531  B = Y15 + U5;
2532  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2533 
2534  *rgba++ = (unsigned char)R;
2535  *rgba++ = (unsigned char)G;
2536  *rgba++ = (unsigned char)B;
2537  *rgba = vpRGBa::alpha_default;
2538  rgba = rgba -12*width+1;
2539  }
2540  yuv+=3*width;
2541  rgba+=12*width;
2542  }
2543 }
2549 void vpImageConvert::YVU9ToRGB(unsigned char* yuv, unsigned char* rgb,
2550  unsigned int height, unsigned int width)
2551 {
2552  // std::cout << "call optimized ConvertYVU9ToRGB()" << std::endl;
2553  int U, V, R, G, B, V2, U5, UV;
2554  int Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9, Y10, Y11, Y12, Y13, Y14, Y15;
2555  unsigned int size = width*height;
2556  unsigned char* iV = yuv + size;
2557  unsigned char* iU = yuv + 17*size/16;
2558  for(unsigned int i = 0; i<height/4; i++)
2559  {
2560  for(unsigned int j = 0; j < width/4 ; j++)
2561  {
2562  U = (int)((*iU++ - 128) * 0.354);
2563  U5 = 5*U;
2564  V = (int)((*iV++ - 128) * 0.707);
2565  V2 = 2*V;
2566  UV = - U - V;
2567  Y0 = *yuv++;
2568  Y1 = *yuv++;
2569  Y2 = *yuv++;
2570  Y3 = *yuv;
2571  yuv = yuv+width-3;
2572  Y4 = *yuv++;
2573  Y5 = *yuv++;
2574  Y6 = *yuv++;
2575  Y7 = *yuv;
2576  yuv = yuv+width-3;
2577  Y8 = *yuv++;
2578  Y9 = *yuv++;
2579  Y10 = *yuv++;
2580  Y11 = *yuv;
2581  yuv = yuv+width-3;
2582  Y12 = *yuv++;
2583  Y13 = *yuv++;
2584  Y14 = *yuv++;
2585  Y15 = *yuv;
2586  yuv = yuv-3*width+1;
2587 
2588  // Original equations
2589  // R = Y + 1.402 V
2590  // G = Y - 0.344 U - 0.714 V
2591  // B = Y + 1.772 U
2592  R = Y0 + V2;
2593  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2594 
2595  G = Y0 + UV;
2596  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2597 
2598  B = Y0 + U5;
2599  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2600 
2601  *rgb++ = (unsigned char)R;
2602  *rgb++ = (unsigned char)G;
2603  *rgb++ = (unsigned char)B;
2604 
2605  //---
2606  R = Y1 + V2;
2607  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2608 
2609  G = Y1 + UV;
2610  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2611 
2612  B = Y1 + U5;
2613  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2614 
2615  *rgb++ = (unsigned char)R;
2616  *rgb++ = (unsigned char)G;
2617  *rgb++ = (unsigned char)B;
2618 
2619  //---
2620  R = Y2 + V2;
2621  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2622 
2623  G = Y2 + UV;
2624  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2625 
2626  B = Y2 + U5;
2627  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2628 
2629  *rgb++ = (unsigned char)R;
2630  *rgb++ = (unsigned char)G;
2631  *rgb++ = (unsigned char)B;
2632 
2633  //---
2634  R = Y3 + V2;
2635  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2636 
2637  G = Y3 + UV;
2638  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2639 
2640  B = Y3 + U5;
2641  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2642 
2643  *rgb++ = (unsigned char)R;
2644  *rgb++ = (unsigned char)G;
2645  *rgb = (unsigned char)B;
2646  rgb = rgb + 3*width-11;
2647 
2648  R = Y4 + V2;
2649  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2650 
2651  G = Y4 + UV;
2652  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2653 
2654  B = Y4 + U5;
2655  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2656 
2657  *rgb++ = (unsigned char)R;
2658  *rgb++ = (unsigned char)G;
2659  *rgb++ = (unsigned char)B;
2660 
2661  //---
2662  R = Y5 + V2;
2663  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2664 
2665  G = Y5 + UV;
2666  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2667 
2668  B = Y5 + U5;
2669  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2670 
2671  *rgb++ = (unsigned char)R;
2672  *rgb++ = (unsigned char)G;
2673  *rgb++ = (unsigned char)B;
2674 
2675  //---
2676  R = Y6 + V2;
2677  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2678 
2679  G = Y6 + UV;
2680  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2681 
2682  B = Y6 + U5;
2683  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2684 
2685  *rgb++ = (unsigned char)R;
2686  *rgb++ = (unsigned char)G;
2687  *rgb++ = (unsigned char)B;
2688 
2689  //---
2690  R = Y7 + V2;
2691  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2692 
2693  G = Y7 + UV;
2694  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2695 
2696  B = Y7 + U5;
2697  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2698 
2699  *rgb++ = (unsigned char)R;
2700  *rgb++ = (unsigned char)G;
2701  *rgb = (unsigned char)B;
2702  rgb = rgb + 3*width-11;
2703 
2704  R = Y8 + V2;
2705  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2706 
2707  G = Y8 + UV;
2708  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2709 
2710  B = Y8 + U5;
2711  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2712 
2713  *rgb++ = (unsigned char)R;
2714  *rgb++ = (unsigned char)G;
2715  *rgb++ = (unsigned char)B;
2716 
2717  //---
2718  R = Y9 + V2;
2719  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2720 
2721  G = Y9 + UV;
2722  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2723 
2724  B = Y9 + U5;
2725  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2726 
2727  *rgb++ = (unsigned char)R;
2728  *rgb++ = (unsigned char)G;
2729  *rgb++ = (unsigned char)B;
2730 
2731  //---
2732  R = Y10 + V2;
2733  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2734 
2735  G = Y10 + UV;
2736  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2737 
2738  B = Y10 + U5;
2739  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2740 
2741  *rgb++ = (unsigned char)R;
2742  *rgb++ = (unsigned char)G;
2743  *rgb++ = (unsigned char)B;
2744 
2745  //---
2746  R = Y11 + V2;
2747  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2748 
2749  G = Y11 + UV;
2750  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2751 
2752  B = Y11 + U5;
2753  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2754 
2755  *rgb++ = (unsigned char)R;
2756  *rgb++ = (unsigned char)G;
2757  *rgb = (unsigned char)B;
2758  rgb = rgb + 3*width-11;
2759 
2760  R = Y12 + V2;
2761  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2762 
2763  G = Y12 + UV;
2764  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2765 
2766  B = Y12 + U5;
2767  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2768 
2769  *rgb++ = (unsigned char)R;
2770  *rgb++ = (unsigned char)G;
2771  *rgb++ = (unsigned char)B;
2772 
2773  //---
2774  R = Y13 + V2;
2775  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2776 
2777  G = Y13 + UV;
2778  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2779 
2780  B = Y13 + U5;
2781  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2782 
2783  *rgb++ = (unsigned char)R;
2784  *rgb++ = (unsigned char)G;
2785  *rgb++ = (unsigned char)B;
2786 
2787  //---
2788  R = Y14 + V2;
2789  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2790 
2791  G = Y14 + UV;
2792  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2793 
2794  B = Y14 + U5;
2795  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2796 
2797  *rgb++ = (unsigned char)R;
2798  *rgb++ = (unsigned char)G;
2799  *rgb++ = (unsigned char)B;
2800 
2801  //---
2802  R = Y15 + V2;
2803  if ((R >> 8) > 0) R = 255; else if (R < 0) R = 0;
2804 
2805  G = Y15 + UV;
2806  if ((G >> 8) > 0) G = 255; else if (G < 0) G = 0;
2807 
2808  B = Y15 + U5;
2809  if ((B >> 8) > 0) B = 255; else if (B < 0) B = 0;
2810 
2811  *rgb++ = (unsigned char)R;
2812  *rgb++ = (unsigned char)G;
2813  *rgb++ = (unsigned char)B;
2814  rgb = rgb -9*width+1;
2815  }
2816  yuv+=3*width;
2817  rgb+=9*width;
2818  }
2819 }
2820 
2828 void vpImageConvert::RGBToRGBa(unsigned char* rgb, unsigned char* rgba, unsigned int size)
2829 {
2830  unsigned char *pt_input = rgb;
2831  unsigned char *pt_end = rgb + 3*size;
2832  unsigned char *pt_output = rgba;
2833 
2834  while(pt_input != pt_end) {
2835  *(pt_output++) = *(pt_input++) ; // R
2836  *(pt_output++) = *(pt_input++) ; // G
2837  *(pt_output++) = *(pt_input++) ; // B
2838  *(pt_output++) = vpRGBa::alpha_default; // A
2839  }
2840 }
2841 
2849 void vpImageConvert::RGBaToRGB(unsigned char* rgba, unsigned char* rgb, unsigned int size)
2850 {
2851  unsigned char *pt_input = rgba;
2852  unsigned char *pt_end = rgba + 4*size;
2853  unsigned char *pt_output = rgb;
2854 
2855  while(pt_input != pt_end) {
2856  *(pt_output++) = *(pt_input++) ; // R
2857  *(pt_output++) = *(pt_input++) ; // G
2858  *(pt_output++) = *(pt_input++) ; // B
2859  pt_input++ ;
2860  }
2861 }
2868 void vpImageConvert::RGBToGrey(unsigned char* rgb, unsigned char* grey, unsigned int size)
2869 {
2870 #if VISP_HAVE_SSSE3
2871  unsigned int i = 0;
2872 
2873  if(size >= 16) {
2874  //Mask to select R component
2875  const __m128i mask_R1 = _mm_set_epi8(
2876  -1, -1, -1, -1, 15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1
2877  );
2878  const __m128i mask_R2 = _mm_set_epi8(
2879  5, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
2880  );
2881  const __m128i mask_R3 = _mm_set_epi8(
2882  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1
2883  );
2884  const __m128i mask_R4 = _mm_set_epi8(
2885  13, -1, 10, -1, 7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1
2886  );
2887 
2888  //Mask to select G component
2889  const __m128i mask_G1 = _mm_set_epi8(
2890  -1, -1, -1, -1, -1, -1, 13, -1, 10, -1, 7, -1, 4, -1, 1, -1
2891  );
2892  const __m128i mask_G2 = _mm_set_epi8(
2893  6, -1, 3, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
2894  );
2895  const __m128i mask_G3 = _mm_set_epi8(
2896  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 12, -1, 9, -1
2897  );
2898  const __m128i mask_G4 = _mm_set_epi8(
2899  14, -1, 11, -1, 8, -1, 5, -1, 2, -1, -1, -1, -1, -1, -1, -1
2900  );
2901 
2902  //Mask to select B component
2903  const __m128i mask_B1 = _mm_set_epi8(
2904  -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1, 5, -1, 2, -1
2905  );
2906  const __m128i mask_B2 = _mm_set_epi8(
2907  7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
2908  );
2909  const __m128i mask_B3 = _mm_set_epi8(
2910  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 10, -1
2911  );
2912  const __m128i mask_B4 = _mm_set_epi8(
2913  15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1, -1, -1, -1, -1
2914  );
2915 
2916  //Mask to select the gray component
2917  const __m128i mask_low1 = _mm_set_epi8(
2918  -1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1
2919  );
2920  const __m128i mask_low2 = _mm_set_epi8(
2921  15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1
2922  );
2923 
2924  //Coefficients RGB to Gray
2925  const __m128i coeff_R = _mm_set_epi16(
2926  13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933
2927  );
2928  const __m128i coeff_G = _mm_set_epi16(
2929  (short int) 46871, (short int) 46871, (short int) 46871, (short int) 46871,
2930  (short int) 46871, (short int) 46871, (short int) 46871, (short int) 46871
2931  );
2932  const __m128i coeff_B = _mm_set_epi16(
2933  4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732
2934  );
2935 
2936  for(; i <= size - 16; i+=16) {
2937  //Process 16 color pixels
2938  const __m128i data1 = _mm_loadu_si128((const __m128i*) rgb);
2939  const __m128i data2 = _mm_loadu_si128((const __m128i*) (rgb + 16));
2940  const __m128i data3 = _mm_loadu_si128((const __m128i*) (rgb + 32));
2941 
2942  const __m128i red_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2) );
2943  const __m128i green_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2) );
2944  const __m128i blue_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2) );
2945 
2946  const __m128i grays_0_7 =
2947  _mm_adds_epu16(
2948  _mm_mulhi_epu16(red_0_7, coeff_R),
2949  _mm_adds_epu16(
2950  _mm_mulhi_epu16(green_0_7, coeff_G),
2951  _mm_mulhi_epu16(blue_0_7, coeff_B)
2952  ));
2953 
2954  const __m128i red_8_15 = _mm_or_si128( _mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4) );
2955  const __m128i green_8_15 = _mm_or_si128( _mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4) );
2956  const __m128i blue_8_15 = _mm_or_si128( _mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4) );
2957 
2958  const __m128i grays_8_15 =
2959  _mm_adds_epu16(
2960  _mm_mulhi_epu16(red_8_15, coeff_R),
2961  _mm_adds_epu16(
2962  _mm_mulhi_epu16(green_8_15, coeff_G),
2963  _mm_mulhi_epu16(blue_8_15, coeff_B)
2964  ));
2965 
2966  _mm_storeu_si128( (__m128i*) grey, _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1), _mm_shuffle_epi8(grays_8_15, mask_low2)) );
2967 
2968  rgb += 48;
2969  grey += 16;
2970  }
2971  }
2972 
2973  for(; i < size; i++) {
2974  *grey = (unsigned char) (0.2126 * (*rgb)
2975  + 0.7152 * (*(rgb + 1))
2976  + 0.0722 * (*(rgb + 2)) );
2977 
2978  rgb += 3;
2979  ++grey;
2980  }
2981 #else
2982  unsigned char *pt_input = rgb;
2983  unsigned char* pt_end = rgb + size*3;
2984  unsigned char *pt_output = grey;
2985 
2986  while(pt_input != pt_end) {
2987  *pt_output = (unsigned char) (0.2126 * (*pt_input)
2988  + 0.7152 * (*(pt_input + 1))
2989  + 0.0722 * (*(pt_input + 2)) );
2990  pt_input += 3;
2991  pt_output ++;
2992  }
2993 #endif
2994 }
3002 void vpImageConvert::RGBaToGrey(unsigned char* rgba, unsigned char* grey, unsigned int size)
3003 {
3004 #if VISP_HAVE_SSSE3
3005  unsigned int i = 0;
3006 
3007  if(size >= 16) {
3008  //Mask to select R component
3009  const __m128i mask_R1 = _mm_set_epi8(
3010  -1, -1, -1, -1, -1, -1, -1, -1, 12, -1, 8, -1, 4, -1, 0, -1
3011  );
3012  const __m128i mask_R2 = _mm_set_epi8(
3013  12, -1, 8, -1, 4, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1
3014  );
3015 
3016  //Mask to select G component
3017  const __m128i mask_G1 = _mm_set_epi8(
3018  -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 9, -1, 5, -1, 1, -1
3019  );
3020  const __m128i mask_G2 = _mm_set_epi8(
3021  13, -1, 9, -1, 5, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1
3022  );
3023 
3024  //Mask to select B component
3025  const __m128i mask_B1 = _mm_set_epi8(
3026  -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 10, -1, 6, -1, 2, -1
3027  );
3028  const __m128i mask_B2 = _mm_set_epi8(
3029  14, -1, 10, -1, 6, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1
3030  );
3031 
3032  //Mask to select the gray component
3033  const __m128i mask_low1 = _mm_set_epi8(
3034  -1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1
3035  );
3036  const __m128i mask_low2 = _mm_set_epi8(
3037  15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1
3038  );
3039 
3040  //Coefficients RGB to Gray
3041  const __m128i coeff_R = _mm_set_epi16(
3042  13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933
3043  );
3044  const __m128i coeff_G = _mm_set_epi16(
3045  (short int) 46871, (short int) 46871, (short int) 46871, (short int) 46871,
3046  (short int) 46871, (short int) 46871, (short int) 46871, (short int) 46871
3047  );
3048  const __m128i coeff_B = _mm_set_epi16(
3049  4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732
3050  );
3051 
3052  for(; i <= size - 16; i+=16) {
3053  //Process 2*4 color pixels
3054  const __m128i data1 = _mm_loadu_si128((const __m128i*) rgba);
3055  const __m128i data2 = _mm_loadu_si128((const __m128i*) (rgba + 16));
3056 
3057  const __m128i red_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2) );
3058  const __m128i green_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2) );
3059  const __m128i blue_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2) );
3060 
3061  const __m128i grays_0_7 =
3062  _mm_adds_epu16(
3063  _mm_mulhi_epu16(red_0_7, coeff_R),
3064  _mm_adds_epu16(
3065  _mm_mulhi_epu16(green_0_7, coeff_G),
3066  _mm_mulhi_epu16(blue_0_7, coeff_B)
3067  ));
3068 
3069  //Process next 2*4 color pixels
3070  const __m128i data3 = _mm_loadu_si128((const __m128i*) (rgba + 32));
3071  const __m128i data4 = _mm_loadu_si128((const __m128i*) (rgba + 48));
3072 
3073  const __m128i red_8_15 = _mm_or_si128( _mm_shuffle_epi8(data3, mask_R1), _mm_shuffle_epi8(data4, mask_R2) );
3074  const __m128i green_8_15 = _mm_or_si128( _mm_shuffle_epi8(data3, mask_G1), _mm_shuffle_epi8(data4, mask_G2) );
3075  const __m128i blue_8_15 = _mm_or_si128( _mm_shuffle_epi8(data3, mask_B1), _mm_shuffle_epi8(data4, mask_B2) );
3076 
3077  const __m128i grays_8_15 =
3078  _mm_adds_epu16(
3079  _mm_mulhi_epu16(red_8_15, coeff_R),
3080  _mm_adds_epu16(
3081  _mm_mulhi_epu16(green_8_15, coeff_G),
3082  _mm_mulhi_epu16(blue_8_15, coeff_B)
3083  ));
3084 
3085  _mm_storeu_si128( (__m128i*) grey, _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1), _mm_shuffle_epi8(grays_8_15, mask_low2)) );
3086 
3087  rgba += 64;
3088  grey += 16;
3089  }
3090  }
3091 
3092  for(; i < size; i++) {
3093  *grey = (unsigned char) (0.2126 * (*rgba)
3094  + 0.7152 * (*(rgba + 1))
3095  + 0.0722 * (*(rgba + 2)) );
3096 
3097  rgba += 4;
3098  ++grey;
3099  }
3100 #else
3101  unsigned char *pt_input = rgba;
3102  unsigned char* pt_end = rgba + size*4;
3103  unsigned char *pt_output = grey;
3104 
3105  while(pt_input != pt_end) {
3106  *pt_output = (unsigned char) (0.2126 * (*pt_input)
3107  + 0.7152 * (*(pt_input + 1))
3108  + 0.0722 * (*(pt_input + 2)) );
3109  pt_input += 4;
3110  pt_output ++;
3111  }
3112 #endif
3113 }
3114 
3120 void
3121 vpImageConvert::GreyToRGBa(unsigned char* grey, unsigned char* rgba, unsigned int size)
3122 {
3123  unsigned char *pt_input = grey;
3124  unsigned char *pt_end = grey + size;
3125  unsigned char *pt_output = rgba;
3126 
3127  while(pt_input != pt_end) {
3128  unsigned char p = *pt_input ;
3129  *(pt_output ) = p ; // R
3130  *(pt_output + 1) = p ; // G
3131  *(pt_output + 2) = p ; // B
3132  *(pt_output + 3) = vpRGBa::alpha_default ; // A
3133 
3134  pt_input ++;
3135  pt_output += 4;
3136  }
3137 }
3138 
3143 void
3144 vpImageConvert::GreyToRGB(unsigned char* grey, unsigned char* rgb, unsigned int size)
3145 {
3146  unsigned char *pt_input = grey;
3147  unsigned char* pt_end = grey + size;
3148  unsigned char *pt_output = rgb;
3149 
3150  while(pt_input != pt_end) {
3151  unsigned char p = *pt_input ;
3152  *(pt_output ) = p ; // R
3153  *(pt_output + 1) = p ; // G
3154  *(pt_output + 2) = p ; // B
3155 
3156  pt_input ++;
3157  pt_output += 3;
3158  }
3159 }
3160 
3161 
3168 void
3169 vpImageConvert::BGRToRGBa(unsigned char * bgr, unsigned char * rgba,
3170  unsigned int width, unsigned int height, bool flip)
3171 {
3172  //if we have to flip the image, we start from the end last scanline so the
3173  //step is negative
3174  int lineStep = (flip) ? -(int)(width*3) : (int)(width*3);
3175 
3176  //starting source address = last line if we need to flip the image
3177  unsigned char * src = (flip) ? (bgr+(width*height*3)+lineStep) : bgr;
3178 
3179  for(unsigned int i=0 ; i < height ; i++)
3180  {
3181  unsigned char *line = src;
3182  for(unsigned int j=0 ; j < width ; j++)
3183  {
3184  *rgba++ = *(line+2);
3185  *rgba++ = *(line+1);
3186  *rgba++ = *(line+0);
3187  *rgba++ = vpRGBa::alpha_default;
3188 
3189  line+=3;
3190  }
3191  //go to the next line
3192  src+=lineStep;
3193  }
3194 }
3195 
3201 void
3202 vpImageConvert::BGRToGrey(unsigned char * bgr, unsigned char * grey,
3203  unsigned int width, unsigned int height, bool flip)
3204 {
3205 #if VISP_HAVE_SSSE3
3206  //Mask to select B component
3207  const __m128i mask_B1 = _mm_set_epi8(
3208  -1, -1, -1, -1, 15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1
3209  );
3210  const __m128i mask_B2 = _mm_set_epi8(
3211  5, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
3212  );
3213  const __m128i mask_B3 = _mm_set_epi8(
3214  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1
3215  );
3216  const __m128i mask_B4 = _mm_set_epi8(
3217  13, -1, 10, -1, 7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1
3218  );
3219 
3220  //Mask to select G component
3221  const __m128i mask_G1 = _mm_set_epi8(
3222  -1, -1, -1, -1, -1, -1, 13, -1, 10, -1, 7, -1, 4, -1, 1, -1
3223  );
3224  const __m128i mask_G2 = _mm_set_epi8(
3225  6, -1, 3, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
3226  );
3227  const __m128i mask_G3 = _mm_set_epi8(
3228  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 12, -1, 9, -1
3229  );
3230  const __m128i mask_G4 = _mm_set_epi8(
3231  14, -1, 11, -1, 8, -1, 5, -1, 2, -1, -1, -1, -1, -1, -1, -1
3232  );
3233 
3234  //Mask to select R component
3235  const __m128i mask_R1 = _mm_set_epi8(
3236  -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1, 5, -1, 2, -1
3237  );
3238  const __m128i mask_R2 = _mm_set_epi8(
3239  7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
3240  );
3241  const __m128i mask_R3 = _mm_set_epi8(
3242  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 10, -1
3243  );
3244  const __m128i mask_R4 = _mm_set_epi8(
3245  15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1, -1, -1, -1, -1
3246  );
3247 
3248  //Mask to select the gray component
3249  const __m128i mask_low1 = _mm_set_epi8(
3250  -1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1
3251  );
3252  const __m128i mask_low2 = _mm_set_epi8(
3253  15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1
3254  );
3255 
3256  //Coefficients RGB to Gray
3257  // const __m128i coeff_R = _mm_set_epi8(
3258  // 54, -1, 54, -1, 54, -1, 54, -1, 54, -1, 54, -1, 54, -1, 54, -1
3259  // );
3260  // const __m128i coeff_G = _mm_set_epi8(
3261  // 183, -1, 183, -1, 183, -1, 183, -1, 183, -1, 183, -1, 183, -1, 183, -1
3262  // );
3263  // const __m128i coeff_B = _mm_set_epi8(
3264  // 18, -1, 18, -1, 18, -1, 18, -1, 18, -1, 18, -1, 18, -1, 18, -1
3265  // );
3266  // const __m128i coeff_R = _mm_set_epi16(
3267  // 6969*2, 6969*2, 6969*2, 6969*2, 6969*2, 6969*2, 6969*2, 6969*2
3268  // );
3269  // const __m128i coeff_G = _mm_set_epi16(
3270  // 23434*2, 23434*2, 23434*2, 23434*2, 23434*2, 23434*2, 23434*2, 23434*2
3271  // );
3272  // const __m128i coeff_B = _mm_set_epi16(
3273  // 2365*2, 2365*2, 2365*2, 2365*2, 2365*2, 2365*2, 2365*2, 2365*2
3274  // );
3275  const __m128i coeff_R = _mm_set_epi16(
3276  13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933
3277  );
3278  const __m128i coeff_G = _mm_set_epi16(
3279  (short int) 46871, (short int) 46871, (short int) 46871, (short int) 46871,
3280  (short int) 46871, (short int) 46871, (short int) 46871, (short int) 46871
3281  );
3282  const __m128i coeff_B = _mm_set_epi16(
3283  4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732
3284  );
3285 
3286  if(flip) {
3287  int i = ((int) height) - 1;
3288  int lineStep = -(int) (width*3);
3289  bgr = bgr + (width * (height-1) * 3);
3290 
3291  unsigned char *linePtr = bgr;
3292  unsigned char r,g,b;
3293 
3294  if(width >= 16) {
3295  for(; i >= 0; i--) {
3296  unsigned int j = 0;
3297 
3298  for(; j <= width - 16; j+=16) {
3299  //Process 16 color pixels
3300  const __m128i data1 = _mm_loadu_si128((const __m128i*) bgr);
3301  const __m128i data2 = _mm_loadu_si128((const __m128i*) (bgr + 16));
3302  const __m128i data3 = _mm_loadu_si128((const __m128i*) (bgr + 32));
3303 
3304  const __m128i red_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2) );
3305  const __m128i green_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2) );
3306  const __m128i blue_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2) );
3307 
3308  const __m128i grays_0_7 =
3309  _mm_adds_epu16(
3310  _mm_mulhi_epu16(red_0_7, coeff_R),
3311  _mm_adds_epu16(
3312  _mm_mulhi_epu16(green_0_7, coeff_G),
3313  _mm_mulhi_epu16(blue_0_7, coeff_B)
3314  ));
3315 
3316  const __m128i red_8_15 = _mm_or_si128( _mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4) );
3317  const __m128i green_8_15 = _mm_or_si128( _mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4) );
3318  const __m128i blue_8_15 = _mm_or_si128( _mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4) );
3319 
3320  const __m128i grays_8_15 =
3321  _mm_adds_epu16(
3322  _mm_mulhi_epu16(red_8_15, coeff_R),
3323  _mm_adds_epu16(
3324  _mm_mulhi_epu16(green_8_15, coeff_G),
3325  _mm_mulhi_epu16(blue_8_15, coeff_B)
3326  ));
3327 
3328  _mm_storeu_si128( (__m128i*) grey, _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1), _mm_shuffle_epi8(grays_8_15, mask_low2)) );
3329 
3330  bgr += 48;
3331  grey += 16;
3332  }
3333 
3334  for(; j < width; j++) {
3335  b = *(bgr++);
3336  g = *(bgr++);
3337  r = *(bgr++);
3338  *grey++ = (unsigned char) ( 0.2126 * r + 0.7152 * g + 0.0722 * b);
3339  }
3340 
3341  linePtr += lineStep;
3342  bgr = linePtr;
3343  }
3344  }
3345 
3346  for(; i >= 0; i--) {
3347  for(unsigned int j = 0; j < width; j++) {
3348  b = *(bgr++);
3349  g = *(bgr++);
3350  r = *(bgr++);
3351  *grey++ = (unsigned char) ( 0.2126 * r + 0.7152 * g + 0.0722 * b);
3352  }
3353 
3354  linePtr += lineStep;
3355  bgr = linePtr;
3356  }
3357  } else {
3358  unsigned int i = 0;
3359  unsigned int size = width * height;
3360 
3361  if(size >= 16) {
3362  for(; i <= size - 16; i+=16) {
3363  //Process 16 color pixels
3364  const __m128i data1 = _mm_loadu_si128((const __m128i*) bgr);
3365  const __m128i data2 = _mm_loadu_si128((const __m128i*) (bgr + 16));
3366  const __m128i data3 = _mm_loadu_si128((const __m128i*) (bgr + 32));
3367 
3368  const __m128i red_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2) );
3369  const __m128i green_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2) );
3370  const __m128i blue_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2) );
3371 
3372  const __m128i grays_0_7 =
3373  _mm_adds_epu16(
3374  _mm_mulhi_epu16(red_0_7, coeff_R),
3375  _mm_adds_epu16(
3376  _mm_mulhi_epu16(green_0_7, coeff_G),
3377  _mm_mulhi_epu16(blue_0_7, coeff_B)
3378  ));
3379 
3380  const __m128i red_8_15 = _mm_or_si128( _mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4) );
3381  const __m128i green_8_15 = _mm_or_si128( _mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4) );
3382  const __m128i blue_8_15 = _mm_or_si128( _mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4) );
3383 
3384  const __m128i grays_8_15 =
3385  _mm_adds_epu16(
3386  _mm_mulhi_epu16(red_8_15, coeff_R),
3387  _mm_adds_epu16(
3388  _mm_mulhi_epu16(green_8_15, coeff_G),
3389  _mm_mulhi_epu16(blue_8_15, coeff_B)
3390  ));
3391 
3392  _mm_storeu_si128( (__m128i*) grey, _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1), _mm_shuffle_epi8(grays_8_15, mask_low2)) );
3393 
3394  bgr += 48;
3395  grey += 16;
3396  }
3397  }
3398 
3399  for(; i < size; i++) {
3400  *grey = (unsigned char) (0.2126 * (*(bgr + 2))
3401  + 0.7152 * (*(bgr + 1))
3402  + 0.0722 * (*bgr) );
3403 
3404  bgr += 3;
3405  ++grey;
3406  }
3407  }
3408 #else
3409  //if we have to flip the image, we start from the end last scanline so the
3410  //step is negative
3411  int lineStep = (flip) ? -(int)(width*3) : (int)(width*3);
3412 
3413  //starting source address = last line if we need to flip the image
3414  unsigned char * src = (flip) ? bgr+(width*height*3)+lineStep : bgr;
3415 
3416  for(unsigned int i=0 ; i < height ; i++)
3417  {
3418  unsigned char *line = src;
3419  for(unsigned int j=0 ; j < width ; j++)
3420  {
3421  *grey++ = (unsigned char)( 0.2126 * *(line+2)
3422  + 0.7152 * *(line+1)
3423  + 0.0722 * *(line+0)) ;
3424  line+=3;
3425  }
3426 
3427  //go to the next line
3428  src+=lineStep;
3429  }
3430 #endif
3431 }
3432 
3439 void
3440 vpImageConvert::RGBToRGBa(unsigned char * rgb, unsigned char * rgba,
3441  unsigned int width, unsigned int height, bool flip)
3442 {
3443  //if we have to flip the image, we start from the end last scanline so the
3444  //step is negative
3445  int lineStep = (flip) ? -(int)(width*3) : (int)(width*3);
3446 
3447  //starting source address = last line if we need to flip the image
3448  unsigned char * src = (flip) ? (rgb+(width*height*3)+lineStep) : rgb;
3449 
3450  unsigned int j=0;
3451  unsigned int i=0;
3452 
3453  for(i=0 ; i < height ; i++)
3454  {
3455  unsigned char * line = src;
3456  for( j=0 ; j < width ; j++)
3457  {
3458  *rgba++ = *(line++);
3459  *rgba++ = *(line++);
3460  *rgba++ = *(line++);
3461  *rgba++ = vpRGBa::alpha_default;
3462  }
3463  //go to the next line
3464  src+=lineStep;
3465  }
3466 }
3467 
3473 void
3474 vpImageConvert::RGBToGrey(unsigned char * rgb, unsigned char * grey,
3475  unsigned int width, unsigned int height, bool flip)
3476 {
3477  if(flip) {
3478 #if VISP_HAVE_SSSE3
3479  int i = ((int) height) - 1;
3480  int lineStep = -(int) (width*3);
3481  rgb = rgb + (width * (height-1) * 3);
3482 
3483  unsigned char *linePtr = rgb;
3484  unsigned char r,g,b;
3485 
3486  if(width >= 16) {
3487  //Mask to select R component
3488  const __m128i mask_R1 = _mm_set_epi8(
3489  -1, -1, -1, -1, 15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1
3490  );
3491  const __m128i mask_R2 = _mm_set_epi8(
3492  5, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
3493  );
3494  const __m128i mask_R3 = _mm_set_epi8(
3495  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1
3496  );
3497  const __m128i mask_R4 = _mm_set_epi8(
3498  13, -1, 10, -1, 7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1
3499  );
3500 
3501  //Mask to select G component
3502  const __m128i mask_G1 = _mm_set_epi8(
3503  -1, -1, -1, -1, -1, -1, 13, -1, 10, -1, 7, -1, 4, -1, 1, -1
3504  );
3505  const __m128i mask_G2 = _mm_set_epi8(
3506  6, -1, 3, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
3507  );
3508  const __m128i mask_G3 = _mm_set_epi8(
3509  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 12, -1, 9, -1
3510  );
3511  const __m128i mask_G4 = _mm_set_epi8(
3512  14, -1, 11, -1, 8, -1, 5, -1, 2, -1, -1, -1, -1, -1, -1, -1
3513  );
3514 
3515  //Mask to select B component
3516  const __m128i mask_B1 = _mm_set_epi8(
3517  -1, -1, -1, -1, -1, -1, 14, -1, 11, -1, 8, -1, 5, -1, 2, -1
3518  );
3519  const __m128i mask_B2 = _mm_set_epi8(
3520  7, -1, 4, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
3521  );
3522  const __m128i mask_B3 = _mm_set_epi8(
3523  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, 10, -1
3524  );
3525  const __m128i mask_B4 = _mm_set_epi8(
3526  15, -1, 12, -1, 9, -1, 6, -1, 3, -1, 0, -1, -1, -1, -1, -1
3527  );
3528 
3529  //Mask to select the gray component
3530  const __m128i mask_low1 = _mm_set_epi8(
3531  -1, -1, -1, -1, -1, -1, -1, -1, 15, 13, 11, 9, 7, 5, 3, 1
3532  );
3533  const __m128i mask_low2 = _mm_set_epi8(
3534  15, 13, 11, 9, 7, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1
3535  );
3536 
3537  //Coefficients RGB to Gray
3538  const __m128i coeff_R = _mm_set_epi16(
3539  13933, 13933, 13933, 13933, 13933, 13933, 13933, 13933
3540  );
3541  const __m128i coeff_G = _mm_set_epi16(
3542  (short int) 46871, (short int) 46871, (short int) 46871, (short int) 46871,
3543  (short int) 46871, (short int) 46871, (short int) 46871, (short int) 46871
3544  );
3545  const __m128i coeff_B = _mm_set_epi16(
3546  4732, 4732, 4732, 4732, 4732, 4732, 4732, 4732
3547  );
3548 
3549  for(; i >= 0; i--) {
3550  unsigned int j = 0;
3551 
3552  for(; j <= width - 16; j+=16) {
3553  //Process 16 color pixels
3554  const __m128i data1 = _mm_loadu_si128((const __m128i*) rgb);
3555  const __m128i data2 = _mm_loadu_si128((const __m128i*) (rgb + 16));
3556  const __m128i data3 = _mm_loadu_si128((const __m128i*) (rgb + 32));
3557 
3558  const __m128i red_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_R1), _mm_shuffle_epi8(data2, mask_R2) );
3559  const __m128i green_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_G1), _mm_shuffle_epi8(data2, mask_G2) );
3560  const __m128i blue_0_7 = _mm_or_si128( _mm_shuffle_epi8(data1, mask_B1), _mm_shuffle_epi8(data2, mask_B2) );
3561 
3562  const __m128i grays_0_7 =
3563  _mm_adds_epu16(
3564  _mm_mulhi_epu16(red_0_7, coeff_R),
3565  _mm_adds_epu16(
3566  _mm_mulhi_epu16(green_0_7, coeff_G),
3567  _mm_mulhi_epu16(blue_0_7, coeff_B)
3568  ));
3569 
3570  const __m128i red_8_15 = _mm_or_si128( _mm_shuffle_epi8(data2, mask_R3), _mm_shuffle_epi8(data3, mask_R4) );
3571  const __m128i green_8_15 = _mm_or_si128( _mm_shuffle_epi8(data2, mask_G3), _mm_shuffle_epi8(data3, mask_G4) );
3572  const __m128i blue_8_15 = _mm_or_si128( _mm_shuffle_epi8(data2, mask_B3), _mm_shuffle_epi8(data3, mask_B4) );
3573 
3574  const __m128i grays_8_15 =
3575  _mm_adds_epu16(
3576  _mm_mulhi_epu16(red_8_15, coeff_R),
3577  _mm_adds_epu16(
3578  _mm_mulhi_epu16(green_8_15, coeff_G),
3579  _mm_mulhi_epu16(blue_8_15, coeff_B)
3580  ));
3581 
3582  _mm_storeu_si128( (__m128i*) grey, _mm_or_si128(_mm_shuffle_epi8(grays_0_7, mask_low1), _mm_shuffle_epi8(grays_8_15, mask_low2)) );
3583 
3584  rgb += 48;
3585  grey += 16;
3586  }
3587 
3588  for(; j < width; j++) {
3589  r = *(rgb++);
3590  g = *(rgb++);
3591  b = *(rgb++);
3592  *grey++ = (unsigned char) ( 0.2126 * r + 0.7152 * g + 0.0722 * b);
3593  }
3594 
3595  linePtr += lineStep;
3596  rgb = linePtr;
3597  }
3598  }
3599 
3600  for(; i >= 0; i--) {
3601  for(unsigned int j = 0; j < width; j++) {
3602  r = *(rgb++);
3603  g = *(rgb++);
3604  b = *(rgb++);
3605  *grey++ = (unsigned char) ( 0.2126 * r + 0.7152 * g + 0.0722 * b);
3606  }
3607 
3608  linePtr += lineStep;
3609  rgb = linePtr;
3610  }
3611 #else
3612  //if we have to flip the image, we start from the end last scanline so the
3613  //step is negative
3614  int lineStep = (flip) ? -(int)(width*3) : (int)(width*3);
3615 
3616  //starting source address = last line if we need to flip the image
3617  unsigned char * src = (flip) ? rgb+(width*height*3)+lineStep : rgb;
3618 
3619  unsigned int j=0;
3620  unsigned int i=0;
3621 
3622  unsigned r,g,b;
3623 
3624  for(i=0 ; i < height ; i++)
3625  {
3626  unsigned char * line = src;
3627  for( j=0 ; j < width ; j++)
3628  {
3629  r = *(line++);
3630  g = *(line++);
3631  b = *(line++);
3632  *grey++ = (unsigned char)( 0.2126 * r + 0.7152 * g + 0.0722 * b) ;
3633  }
3634 
3635  //go to the next line
3636  src+=lineStep;
3637  }
3638 #endif
3639  } else {
3640  RGBToGrey(rgb, grey, width*height);
3641  }
3642 }
3643 
3649 void vpImageConvert::computeYCbCrLUT()
3650 {
3651  if (YCbCrLUTcomputed == false) {
3652  int index = 256;
3653 
3654  while (index-- ) {
3655 
3656  int aux = index - 128;
3657  vpImageConvert::vpCrr[index] = (int)( 364.6610 * aux) >> 8;
3658  vpImageConvert::vpCgb[index] = (int)( -89.8779 * aux) >> 8;
3659  vpImageConvert::vpCgr[index] = (int)(-185.8154 * aux) >> 8;
3660  vpImageConvert::vpCbb[index] = (int)( 460.5724 * aux) >> 8;
3661  }
3662 
3663  YCbCrLUTcomputed = true;
3664  }
3665 }
3666 
3667 
3687 void vpImageConvert::YCbCrToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
3688 {
3689  unsigned char *cbv;
3690  unsigned char *crv;
3691  unsigned char *pt_ycbcr = ycbcr;
3692  unsigned char *pt_rgb = rgb;
3693  cbv = pt_ycbcr + 1;
3694  crv = pt_ycbcr + 3;
3695 
3696  vpImageConvert::computeYCbCrLUT();
3697 
3698  int col = 0;
3699 
3700  while (size--) {
3701  int val_r, val_g, val_b;
3702  if (!(col++ % 2)) {
3703  cbv = pt_ycbcr + 1;
3704  crv = pt_ycbcr + 3;
3705  }
3706 
3707  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
3708  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
3709  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
3710 
3711  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
3712 
3713  *pt_rgb++ = (val_r < 0) ? 0u :
3714  ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
3715  *pt_rgb++ = (val_g < 0) ? 0u :
3716  ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
3717  *pt_rgb++ = (val_b < 0) ? 0u :
3718  ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
3719 
3720  pt_ycbcr += 2;
3721  }
3722 }
3723 
3747 void vpImageConvert::YCbCrToRGBa(unsigned char *ycbcr, unsigned char *rgba, unsigned int size)
3748 {
3749  unsigned char *cbv;
3750  unsigned char *crv;
3751  unsigned char *pt_ycbcr = ycbcr;
3752  unsigned char *pt_rgba = rgba;
3753  cbv = pt_ycbcr + 1;
3754  crv = pt_ycbcr + 3;
3755 
3756  vpImageConvert::computeYCbCrLUT();
3757 
3758  int col = 0;
3759 
3760  while (size--) {
3761  int val_r, val_g, val_b;
3762  if (!(col++ % 2)) {
3763  cbv = pt_ycbcr + 1;
3764  crv = pt_ycbcr + 3;
3765  }
3766 
3767  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
3768  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
3769  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
3770 
3771  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
3772 
3773  *pt_rgba++ = (val_r < 0) ? 0u :
3774  ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
3775  *pt_rgba++ = (val_g < 0) ? 0u :
3776  ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
3777  *pt_rgba++ = (val_b < 0) ? 0u :
3778  ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
3779  *pt_rgba++ = vpRGBa::alpha_default;
3780 
3781  pt_ycbcr += 2;
3782  }
3783 }
3784 
3785 
3802 void vpImageConvert::YCbCrToGrey(unsigned char* yuv, unsigned char* grey, unsigned int size)
3803 {
3804  unsigned int i=0,j=0;
3805 
3806  while( j < size*2)
3807  {
3808  grey[i++] = yuv[j];
3809  grey[i++] = yuv[j+2];
3810  j+=4;
3811  }
3812 }
3813 
3832 void vpImageConvert::YCrCbToRGB(unsigned char *ycrcb, unsigned char *rgb, unsigned int size)
3833 {
3834  unsigned char *cbv;
3835  unsigned char *crv;
3836  unsigned char *pt_ycbcr = ycrcb;
3837  unsigned char *pt_rgb = rgb;
3838  crv = pt_ycbcr + 1;
3839  cbv = pt_ycbcr + 3;
3840 
3841  vpImageConvert::computeYCbCrLUT();
3842 
3843  int col = 0;
3844 
3845  while (size--) {
3846  int val_r, val_g, val_b;
3847  if (!(col++ % 2)) {
3848  crv = pt_ycbcr + 1;
3849  cbv = pt_ycbcr + 3;
3850  }
3851 
3852  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
3853  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
3854  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
3855 
3856  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
3857 
3858  *pt_rgb++ = (val_r < 0) ? 0u :
3859  ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
3860  *pt_rgb++ = (val_g < 0) ? 0u :
3861  ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
3862  *pt_rgb++ = (val_b < 0) ? 0u :
3863  ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
3864 
3865  pt_ycbcr += 2;
3866  }
3867 }
3890 void vpImageConvert::YCrCbToRGBa(unsigned char *ycrcb, unsigned char *rgba, unsigned int size)
3891 {
3892  unsigned char *cbv;
3893  unsigned char *crv;
3894  unsigned char *pt_ycbcr = ycrcb;
3895  unsigned char *pt_rgba = rgba;
3896  crv = pt_ycbcr + 1;
3897  cbv = pt_ycbcr + 3;
3898 
3899  vpImageConvert::computeYCbCrLUT();
3900 
3901  int col = 0;
3902 
3903  while (size--) {
3904  int val_r, val_g, val_b;
3905  if (!(col++ % 2)) {
3906  crv = pt_ycbcr + 1;
3907  cbv = pt_ycbcr + 3;
3908  }
3909 
3910  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
3911  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
3912  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
3913 
3914  vpDEBUG_TRACE(5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b);
3915 
3916  *pt_rgba++ = (val_r < 0) ? 0u :
3917  ((val_r > 255) ? 255u : (unsigned char)val_r); // Red component.
3918  *pt_rgba++ = (val_g < 0) ? 0u :
3919  ((val_g > 255) ? 255u : (unsigned char)val_g); // Green component.
3920  *pt_rgba++ = (val_b < 0) ? 0u :
3921  ((val_b > 255) ? 255u : (unsigned char)val_b); // Blue component.
3922  *pt_rgba++ = vpRGBa::alpha_default;
3923 
3924  pt_ycbcr += 2;
3925  }
3926 }
3927 
3968 {
3969  size_t n = src.getNumberOfPixel();
3970  unsigned int height = src.getHeight();
3971  unsigned int width = src.getWidth();
3972  unsigned char* input;
3973  unsigned char* dst ;
3974 
3975  vpImage<unsigned char>* tabChannel[4];
3976 
3977  /* incrsrc[0] = 0; //init
3978  incrsrc[1] = 0; //step after the first used channel
3979  incrsrc[2] = 0; //step after the second used channel
3980  incrsrc[3] = 0;
3981  incrsrc[4] = 0;
3982  */
3983  tabChannel[0] = pR;
3984  tabChannel[1] = pG;
3985  tabChannel[2] = pB;
3986  tabChannel[3] = pa;
3987 
3988  size_t i; /* ordre */
3989  for(unsigned int j = 0;j < 4;j++){
3990  if(tabChannel[j]!=NULL){
3991  if(tabChannel[j]->getHeight() != height ||
3992  tabChannel[j]->getWidth() != width){
3993  tabChannel[j]->resize(height,width);
3994  }
3995  dst = (unsigned char*)tabChannel[j]->bitmap;
3996 
3997  input = (unsigned char*)src.bitmap+j;
3998  i = 0;
3999 #if 1 //optimization
4000  if (n >= 4) { /* boucle deroulee lsize fois */
4001  n -= 3;
4002  for (; i < n; i += 4) {
4003  *dst = *input; input += 4; dst++;
4004  *dst = *input; input += 4; dst++;
4005  *dst = *input; input += 4; dst++;
4006  *dst = *input; input += 4; dst++;
4007  }
4008  n += 3;
4009  }
4010 #endif
4011  for (; i < n; i++) {
4012  *dst = *input; input += 4; dst ++;
4013  }
4014  }
4015  }
4016 }
4017 
4027  const vpImage<unsigned char> *G,
4028  const vpImage<unsigned char> *B,
4029  const vpImage<unsigned char> *a,
4030  vpImage<vpRGBa> &RGBa) {
4031  //Check if the input channels have all the same dimensions
4032  std::map<unsigned int, unsigned int> mapOfWidths, mapOfHeights;
4033  if(R != NULL) {
4034  mapOfWidths[R->getWidth()]++;
4035  mapOfHeights[R->getHeight()]++;
4036  }
4037 
4038  if(G != NULL) {
4039  mapOfWidths[G->getWidth()]++;
4040  mapOfHeights[G->getHeight()]++;
4041  }
4042 
4043  if(B != NULL) {
4044  mapOfWidths[B->getWidth()]++;
4045  mapOfHeights[B->getHeight()]++;
4046  }
4047 
4048  if(a != NULL) {
4049  mapOfWidths[a->getWidth()]++;
4050  mapOfHeights[a->getHeight()]++;
4051  }
4052 
4053  if(mapOfWidths.size() == 1 && mapOfHeights.size() == 1) {
4054  unsigned int width = mapOfWidths.begin()->first;
4055  unsigned int height = mapOfHeights.begin()->first;
4056 
4057  RGBa.resize(height, width);
4058 
4059  unsigned int size = width*height;
4060  for(unsigned int i = 0; i < size; i++) {
4061  if(R != NULL) {
4062  RGBa.bitmap[i].R = R->bitmap[i];
4063  }
4064 
4065  if(G != NULL) {
4066  RGBa.bitmap[i].G = G->bitmap[i];
4067  }
4068 
4069  if(B != NULL) {
4070  RGBa.bitmap[i].B = B->bitmap[i];
4071  }
4072 
4073  if(a != NULL) {
4074  RGBa.bitmap[i].A = a->bitmap[i];
4075  }
4076  }
4077  } else {
4078  throw vpException(vpException::dimensionError, "Mismatch dimensions !");
4079  }
4080 }
4081 
4092 void vpImageConvert::MONO16ToGrey(unsigned char *grey16, unsigned char *grey, unsigned int size)
4093 {
4094  int i = (((int)size)<<1)-1;
4095  int j = (int)size-1;
4096 
4097  while (i >= 0) {
4098  int y = grey16[i--];
4099  grey[j--] = static_cast<unsigned char>( (y+(grey16[i--]<<8))>>8 );
4100  }
4101 }
4102 
4115 void vpImageConvert::MONO16ToRGBa(unsigned char *grey16, unsigned char *rgba, unsigned int size)
4116 {
4117  int i = (((int)size)<<1)-1;
4118  int j = (int)(size*4-1);
4119 
4120  while (i >= 0) {
4121  int y = grey16[i--];
4122  unsigned char v = static_cast<unsigned char>( (y+(grey16[i--]<<8))>>8 );
4123  rgba[j--] = vpRGBa::alpha_default;
4124  rgba[j--] = v;
4125  rgba[j--] = v;
4126  rgba[j--] = v;
4127  }
4128 }
4129 
4130 void vpImageConvert::HSV2RGB(const double *hue_, const double *saturation_, const double *value_, unsigned char *rgb,
4131  const unsigned int size, const unsigned int step) {
4132  for(unsigned int i = 0; i < size; i++) {
4133  double hue = hue_[i], saturation = saturation_[i], value = value_[i];
4134 
4135  if (vpMath::equal(saturation, 0.0, std::numeric_limits<double>::epsilon())) {
4136  hue = value;
4137  saturation = value;
4138  } else {
4139  double h = hue * 6.0;
4140  double s = saturation;
4141  double v = value;
4142 
4143  if (vpMath::equal(h, 6.0, std::numeric_limits<double>::epsilon())) {
4144  h = 0.0;
4145  }
4146 
4147  double f = h - (int) h;
4148  double p = v * (1.0 - s);
4149  double q = v * (1.0 - s * f);
4150  double t = v * (1.0 - s * (1.0 - f));
4151 
4152  switch ((int) h) {
4153  case 0:
4154  hue = v;
4155  saturation = t;
4156  value = p;
4157  break;
4158 
4159  case 1:
4160  hue = q;
4161  saturation = v;
4162  value = p;
4163  break;
4164 
4165  case 2:
4166  hue = p;
4167  saturation = v;
4168  value = t;
4169  break;
4170 
4171  case 3:
4172  hue = p;
4173  saturation = q;
4174  value = v;
4175  break;
4176 
4177  case 4:
4178  hue = t;
4179  saturation = p;
4180  value = v;
4181  break;
4182 
4183  default: //case 5:
4184  hue = v;
4185  saturation = p;
4186  value = q;
4187  break;
4188  }
4189  }
4190 
4191  rgb[i*step] = (unsigned char) vpMath::round(hue * 255.0);
4192  rgb[i*step + 1] = (unsigned char) vpMath::round(saturation * 255.0);
4193  rgb[i*step + 2] = (unsigned char) vpMath::round(value * 255.0);
4194  if (step == 4) // alpha
4195  rgb[i*step + 3] = vpRGBa::alpha_default;
4196  }
4197 }
4198 
4199 void vpImageConvert::RGB2HSV(const unsigned char *rgb, double *hue, double *saturation, double *value,
4200  const unsigned int size, const unsigned int step) {
4201  for(unsigned int i = 0; i < size; i++) {
4202  double red, green, blue;
4203  double h, s, v;
4204  double min, max;
4205 
4206  red = rgb[i*step] / 255.0;
4207  green = rgb[i*step + 1] / 255.0;
4208  blue = rgb[i*step + 2] / 255.0;
4209 
4210  if (red > green) {
4211  max = (std::max)(red, blue);
4212  min = (std::min)(green, blue);
4213  } else {
4214  max = (std::max)(green, blue);
4215  min = (std::min)(red, blue);
4216  }
4217 
4218  v = max;
4219 
4220  if (!vpMath::equal(max, 0.0, std::numeric_limits<double>::epsilon())) {
4221  s = (max - min) / max;
4222  } else {
4223  s = 0.0;
4224  }
4225 
4226  if (vpMath::equal(s, 0.0, std::numeric_limits<double>::epsilon())) {
4227  h = 0.0;
4228  } else {
4229  double delta = max - min;
4230  if (vpMath::equal(delta, 0.0, std::numeric_limits<double>::epsilon())) {
4231  delta = 1.0;
4232  }
4233 
4234  if (vpMath::equal(red, max, std::numeric_limits<double>::epsilon())) {
4235  h = (green - blue) / delta;
4236  } else if (vpMath::equal(green, max, std::numeric_limits<double>::epsilon())) {
4237  h = 2 + (blue - red) / delta;
4238  } else {
4239  h = 4 + (red - green) / delta;
4240  }
4241 
4242  h /= 6.0;
4243  if (h < 0.0) {
4244  h += 1.0;
4245  } else if (h > 1.0) {
4246  h -= 1.0;
4247  }
4248  }
4249 
4250  hue[i] = h;
4251  saturation[i] = s;
4252  value[i] = v;
4253  }
4254 }
4255 
4267 void vpImageConvert::HSVToRGBa(const double *hue, const double *saturation, const double *value, unsigned char *rgba,
4268  const unsigned int size) {
4269  vpImageConvert::HSV2RGB(hue, saturation, value, rgba, size, 4);
4270 }
4271 
4283 void vpImageConvert::HSVToRGBa(const unsigned char *hue, const unsigned char *saturation, const unsigned char *value,
4284  unsigned char *rgba, const unsigned int size) {
4285  for(unsigned int i = 0; i < size; i++) {
4286  double h = hue[i] / 255.0, s = saturation[i] / 255.0, v = value[i] / 255.0;
4287 
4288  vpImageConvert::HSVToRGBa(&h, &s, &v, (rgba + i*4), 1);
4289  }
4290 }
4291 
4302 void vpImageConvert::RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value,
4303  const unsigned int size) {
4304  vpImageConvert::RGB2HSV(rgba, hue, saturation, value, size, 4);
4305 }
4306 
4317 void vpImageConvert::RGBaToHSV(const unsigned char *rgba, unsigned char *hue, unsigned char *saturation,
4318  unsigned char *value, const unsigned int size) {
4319  for(unsigned int i = 0; i < size; i++) {
4320  double h, s, v;
4321  vpImageConvert::RGBaToHSV((rgba + i*4), &h, &s, &v, 1);
4322 
4323  hue[i] = (unsigned char) (255.0 * h);
4324  saturation[i] = (unsigned char) (255.0 * s);
4325  value[i] = (unsigned char) (255.0 * v);
4326  }
4327 }
4328 
4338 void vpImageConvert::HSVToRGB(const double *hue, const double *saturation, const double *value, unsigned char *rgb,
4339  const unsigned int size) {
4340  vpImageConvert::HSV2RGB(hue, saturation, value, rgb, size, 3);
4341 }
4342 
4352 void vpImageConvert::HSVToRGB(const unsigned char *hue, const unsigned char *saturation, const unsigned char *value,
4353  unsigned char *rgb, const unsigned int size) {
4354  for(unsigned int i = 0; i < size; i++) {
4355  double h = hue[i] / 255.0, s = saturation[i] / 255.0, v = value[i] / 255.0;
4356 
4357  vpImageConvert::HSVToRGB(&h, &s, &v, (rgb + i*3), 1);
4358  }
4359 }
4360 
4370 void vpImageConvert::RGBToHSV(const unsigned char *rgb, double *hue, double *saturation, double *value,
4371  const unsigned int size) {
4372  vpImageConvert::RGB2HSV(rgb, hue, saturation, value, size, 3);
4373 }
4374 
4384 void vpImageConvert::RGBToHSV(const unsigned char *rgb, unsigned char *hue, unsigned char *saturation, unsigned char *value,
4385  const unsigned int size) {
4386  for(unsigned int i = 0; i < size; i++) {
4387  double h, s, v;
4388 
4389  vpImageConvert::RGBToHSV((rgb + i*3), &h, &s, &v, 1);
4390 
4391  hue[i] = (unsigned char) (255.0 * h);
4392  saturation[i] = (unsigned char) (255.0 * s);
4393  value[i] = (unsigned char) (255.0 * v);
4394  }
4395 }
unsigned int getCols() const
Definition: vpImage.h:166
static void BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static void YUYVToRGBa(unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height)
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int size)
unsigned int getWidth() const
Definition: vpImage.h:226
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
void getMinMaxValue(Type &min, Type &max) const
Look for the minimum and the maximum value within the bitmap.
Definition: vpImage.h:1055
static void RGBToHSV(const unsigned char *rgb, double *hue, double *saturation, double *value, const unsigned int size)
unsigned char B
Blue component.
Definition: vpRGBa.h:155
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false)
Type * bitmap
points toward the bitmap
Definition: vpImage.h:134
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:306
static void YUV422ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
static void YUV420ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int size)
error that can be emited by ViSP classes.
Definition: vpException.h:73
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:154
static void GreyToRGB(unsigned char *grey, unsigned char *rgb, unsigned int size)
static int round(const double x)
Definition: vpMath.h:249
Definition: vpRGBa.h:66
static void YUV444ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
static void YUV420ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YVU9ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YUV422ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
unsigned int getRows() const
Definition: vpImage.h:204
static void YVU9ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
static void YV12ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
unsigned int getSize() const
Definition: vpImage.h:212
static void YCbCrToGrey(unsigned char *ycbcr, unsigned char *grey, unsigned int size)
unsigned char A
Additionnal component.
Definition: vpRGBa.h:156
static void YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
static void MONO16ToRGBa(unsigned char *grey16, unsigned char *rgba, unsigned int size)
unsigned int getNumberOfPixel() const
Definition: vpImage.h:194
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:903
static void merge(const vpImage< unsigned char > *R, const vpImage< unsigned char > *G, const vpImage< unsigned char > *B, const vpImage< unsigned char > *a, vpImage< vpRGBa > &RGBa)
static void RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value, const unsigned int size)
static void YUYVToRGB(unsigned char *yuyv, unsigned char *rgb, unsigned int width, unsigned int height)
static void YUV444ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
static void YUV444ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void YUV411ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
unsigned char R
Red component.
Definition: vpRGBa.h:153
static void HSVToRGBa(const double *hue, const double *saturation, const double *value, unsigned char *rgba, const unsigned int size)
#define vpDEBUG_TRACE
Definition: vpDebug.h:478
unsigned int getHeight() const
Definition: vpImage.h:175
static void YCbCrToRGBa(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void YUV411ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
static void YCrCbToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void HSVToRGB(const double *hue, const double *saturation, const double *value, unsigned char *rgb, const unsigned int size)
static void YCrCbToRGBa(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int size)
static void createDepthHistogram(const vpImage< uint16_t > &src_depth, vpImage< vpRGBa > &dest_rgba)
static void YV12ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
static void YUV420ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)