Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
vpImageConvert.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2021 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Convert image types.
33  *
34  * Authors:
35  * Eric Marchand
36  * Fabien Spindler
37  * Anthony Saunier
38  *
39  *****************************************************************************/
40 
46 #include <map>
47 #include <sstream>
48 
49 #if defined _OPENMP
50 #include <omp.h>
51 #endif
52 
53 // image
54 #include "private/vpBayerConversion.h"
55 #include "private/vpImageConvert_impl.h"
56 #include <Simd/SimdLib.hpp>
57 #include <visp3/core/vpImageConvert.h>
58 
59 bool vpImageConvert::YCbCrLUTcomputed = false;
60 int vpImageConvert::vpCrr[256];
61 int vpImageConvert::vpCgb[256];
62 int vpImageConvert::vpCgr[256];
63 int vpImageConvert::vpCbb[256];
64 
73 void
75 {
76  dest.resize( src.getHeight(), src.getWidth() );
77 
78  GreyToRGBa( src.bitmap, reinterpret_cast< unsigned char * >( dest.bitmap ), src.getWidth(), src.getHeight() );
79 }
80 
90 void
91 vpImageConvert::convert( const vpImage< vpRGBa > &src, vpImage< unsigned char > &dest, unsigned int nThreads )
92 {
93  dest.resize( src.getHeight(), src.getWidth() );
94 
95  RGBaToGrey( reinterpret_cast< unsigned char * >( src.bitmap ), dest.bitmap, src.getWidth(), src.getHeight(),
96  nThreads );
97 }
98 
105 void
107 {
108  dest.resize( src.getHeight(), src.getWidth() );
109  unsigned int max_xy = src.getWidth() * src.getHeight();
110  float min, max;
111 
112  src.getMinMaxValue( min, max );
113 
114  for ( unsigned int i = 0; i < max_xy; i++ )
115  {
116  float val = 255.f * ( src.bitmap[i] - min ) / ( max - min );
117  if ( val < 0 )
118  dest.bitmap[i] = 0;
119  else if ( val > 255 )
120  dest.bitmap[i] = 255;
121  else
122  dest.bitmap[i] = (unsigned char)val;
123  }
124 }
125 
131 void
133 {
134  dest.resize( src.getHeight(), src.getWidth() );
135  for ( unsigned int i = 0; i < src.getHeight() * src.getWidth(); i++ )
136  dest.bitmap[i] = (float)src.bitmap[i];
137 }
138 
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  {
156  double val = 255. * ( src.bitmap[i] - min ) / ( max - min );
157  if ( val < 0 )
158  dest.bitmap[i] = 0;
159  else if ( val > 255 )
160  dest.bitmap[i] = 255;
161  else
162  dest.bitmap[i] = (unsigned char)val;
163  }
164 }
165 
172 void
173 vpImageConvert::convert( const vpImage< uint16_t > &src, vpImage< unsigned char > &dest, unsigned char bitshift )
174 {
175  dest.resize( src.getHeight(), src.getWidth() );
176 
177  for ( unsigned int i = 0; i < src.getSize(); i++ )
178  dest.bitmap[i] = static_cast< unsigned char >( src.bitmap[i] >> bitshift );
179 }
180 
187 void
188 vpImageConvert::convert( const vpImage< unsigned char > &src, vpImage< uint16_t > &dest, unsigned char bitshift )
189 {
190  dest.resize( src.getHeight(), src.getWidth() );
191 
192  for ( unsigned int i = 0; i < src.getSize(); i++ )
193  dest.bitmap[i] = static_cast< unsigned char >( src.bitmap[i] << bitshift );
194 }
195 
201 void
203 {
204  dest.resize( src.getHeight(), src.getWidth() );
205  for ( unsigned int i = 0; i < src.getHeight() * src.getWidth(); i++ )
206  dest.bitmap[i] = (double)src.bitmap[i];
207 }
208 
216 void
218 {
219  vp_createDepthHistogram(src_depth, dest_rgba);
220 }
221 
228 void
230 {
231  vp_createDepthHistogram(src_depth, dest_depth);
232 }
233 
241 void
243 {
244  vp_createDepthHistogram(src_depth, dest_rgba);
245 }
246 
253 void
255 {
256  vp_createDepthHistogram(src_depth, dest_depth);
257 }
258 
259 
260 #ifdef VISP_HAVE_OPENCV
261 // Deprecated: will be removed with OpenCV transcient from C to C++ api
307 void
308 vpImageConvert::convert( const IplImage *src, vpImage< vpRGBa > &dest, bool flip )
309 {
310  int nChannel = src->nChannels;
311  int depth = src->depth;
312  int height = src->height;
313  int width = src->width;
314  int widthStep = src->widthStep;
315  int lineStep = ( flip ) ? 1 : 0;
316 
317  if ( nChannel == 3 && depth == 8 )
318  {
319  dest.resize( (unsigned int)height, (unsigned int)width );
320 
321  // starting source address
322  unsigned char *input = (unsigned char *)src->imageData;
323  unsigned char *beginOutput = (unsigned char *)dest.bitmap;
324 
325  for ( int i = 0; i < height; i++ )
326  {
327  unsigned char *line = input;
328  unsigned char *output =
329  beginOutput + lineStep * ( 4 * width * ( height - 1 - i ) ) + ( 1 - lineStep ) * 4 * width * i;
330  for ( int j = 0; j < width; j++ )
331  {
332  *( output++ ) = *( line + 2 );
333  *( output++ ) = *( line + 1 );
334  *( output++ ) = *( line );
335  *( output++ ) = vpRGBa::alpha_default;
336 
337  line += 3;
338  }
339  // go to the next line
340  input += widthStep;
341  }
342  }
343  else if ( nChannel == 1 && depth == 8 )
344  {
345  dest.resize( (unsigned int)height, (unsigned int)width );
346  // starting source address
347  unsigned char *input = (unsigned char *)src->imageData;
348  unsigned char *beginOutput = (unsigned char *)dest.bitmap;
349 
350  for ( int i = 0; i < height; i++ )
351  {
352  unsigned char *line = input;
353  unsigned char *output =
354  beginOutput + lineStep * ( 4 * width * ( height - 1 - i ) ) + ( 1 - lineStep ) * 4 * width * i;
355  for ( int j = 0; j < width; j++ )
356  {
357  *output++ = *( line );
358  *output++ = *( line );
359  *output++ = *( line );
360  *output++ = vpRGBa::alpha_default; // alpha
361 
362  line++;
363  }
364  // go to the next line
365  input += widthStep;
366  }
367  }
368 }
369 
412 void
413 vpImageConvert::convert( const IplImage *src, vpImage< unsigned char > &dest, bool flip )
414 {
415  int nChannel = src->nChannels;
416  int depth = src->depth;
417  int height = src->height;
418  int width = src->width;
419  int widthStep = src->widthStep;
420  int lineStep = ( flip ) ? 1 : 0;
421 
422  if ( flip == false )
423  {
424  if ( widthStep == width )
425  {
426  if ( nChannel == 1 && depth == 8 )
427  {
428  dest.resize( (unsigned int)height, (unsigned int)width );
429  memcpy( dest.bitmap, src->imageData, ( size_t )( height * width ) );
430  }
431  if ( nChannel == 3 && depth == 8 )
432  {
433  dest.resize( (unsigned int)height, (unsigned int)width );
434  BGRToGrey( (unsigned char *)src->imageData, dest.bitmap, (unsigned int)width, (unsigned int)height, false );
435  }
436  }
437  else
438  {
439  if ( nChannel == 1 && depth == 8 )
440  {
441  dest.resize( (unsigned int)height, (unsigned int)width );
442  for ( int i = 0; i < height; i++ )
443  {
444  memcpy( dest.bitmap + i * width, src->imageData + i * widthStep, (size_t)width );
445  }
446  }
447  if ( nChannel == 3 && depth == 8 )
448  {
449  dest.resize( (unsigned int)height, (unsigned int)width );
450  for ( int i = 0; i < height; i++ )
451  {
452  BGRToGrey( (unsigned char *)src->imageData + i * widthStep, dest.bitmap + i * width, (unsigned int)width, 1,
453  false );
454  }
455  }
456  }
457  }
458  else
459  {
460  if ( nChannel == 1 && depth == 8 )
461  {
462  dest.resize( (unsigned int)height, (unsigned int)width );
463  unsigned char *beginOutput = (unsigned char *)dest.bitmap;
464  for ( int i = 0; i < height; i++ )
465  {
466  memcpy( beginOutput + lineStep * ( 4 * width * ( height - 1 - i ) ), src->imageData + i * widthStep,
467  (size_t)width );
468  }
469  }
470  if ( nChannel == 3 && depth == 8 )
471  {
472  dest.resize( (unsigned int)height, (unsigned int)width );
473  // for (int i = 0 ; i < height ; i++){
474  BGRToGrey( (unsigned char *)src->imageData /*+ i*widthStep*/, dest.bitmap /*+ i*width*/, (unsigned int)width,
475  (unsigned int)height /*1*/, true );
476  //}
477  }
478  }
479 }
480 
524 void
525 vpImageConvert::convert( const vpImage< vpRGBa > &src, IplImage *&dest )
526 {
527  int height = (int)src.getHeight();
528  int width = (int)src.getWidth();
529  CvSize size = cvSize( width, height );
530  int depth = 8;
531  int channels = 3;
532  if ( dest != NULL )
533  {
534  if ( dest->nChannels != channels || dest->depth != depth || dest->height != height || dest->width != width )
535  {
536  if ( dest->nChannels != 0 )
537  cvReleaseImage( &dest );
538  dest = cvCreateImage( size, depth, channels );
539  }
540  }
541  else
542  dest = cvCreateImage( size, depth, channels );
543 
544  // starting source address
545  unsigned char *input = (unsigned char *)src.bitmap; // rgba image
546  unsigned char *output = (unsigned char *)dest->imageData; // bgr image
547 
548  int j = 0;
549  int i = 0;
550  int widthStep = dest->widthStep;
551 
552  for ( i = 0; i < height; i++ )
553  {
554  output = (unsigned char *)dest->imageData + i * widthStep;
555  unsigned char *line = input;
556  for ( j = 0; j < width; j++ )
557  {
558  *output++ = *( line + 2 ); // B
559  *output++ = *( line + 1 ); // G
560  *output++ = *( line ); // R
561 
562  line += 4;
563  }
564  // go to the next line
565  input += 4 * width;
566  }
567 }
568 
612 void
613 vpImageConvert::convert( const vpImage< unsigned char > &src, IplImage *&dest )
614 {
615  unsigned int height = src.getHeight();
616  unsigned int width = src.getWidth();
617  CvSize size = cvSize( (int)width, (int)height );
618  int depth = 8;
619  int channels = 1;
620  if ( dest != NULL )
621  {
622  if ( dest->nChannels != channels || dest->depth != depth || dest->height != (int)height ||
623  dest->width != (int)width )
624  {
625  if ( dest->nChannels != 0 )
626  cvReleaseImage( &dest );
627  dest = cvCreateImage( size, depth, channels );
628  }
629  }
630  else
631  dest = cvCreateImage( size, depth, channels );
632 
633  unsigned int widthStep = (unsigned int)dest->widthStep;
634 
635  if ( width == widthStep )
636  {
637  memcpy( dest->imageData, src.bitmap, width * height );
638  }
639  else
640  {
641  // copying each line taking account of the widthStep
642  for ( unsigned int i = 0; i < height; i++ )
643  {
644  memcpy( dest->imageData + i * widthStep, src.bitmap + i * width, width );
645  }
646  }
647 }
648 
649 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
650 
697 void
698 vpImageConvert::convert( const cv::Mat &src, vpImage< vpRGBa > &dest, bool flip )
699 {
700  dest.resize( (unsigned int)src.rows, (unsigned int)src.cols );
701 
702  if ( src.type() == CV_8UC4 )
703  {
704  vpRGBa rgbaVal;
705  for ( unsigned int i = 0; i < dest.getRows(); ++i )
706  for ( unsigned int j = 0; j < dest.getCols(); ++j )
707  {
708  cv::Vec4b tmp = src.at< cv::Vec4b >( (int)i, (int)j );
709  rgbaVal.R = tmp[2];
710  rgbaVal.G = tmp[1];
711  rgbaVal.B = tmp[0];
712  rgbaVal.A = tmp[3];
713  if ( flip )
714  dest[dest.getRows() - i - 1][j] = rgbaVal;
715  else
716  dest[i][j] = rgbaVal;
717  }
718  }
719  else if ( src.type() == CV_8UC3 )
720  {
721  if ( src.isContinuous() && !flip )
722  {
723  SimdRgbToBgra( src.data, src.cols, src.rows, src.step[0], reinterpret_cast< uint8_t * >( dest.bitmap ),
724  dest.getWidth() * sizeof( vpRGBa ), vpRGBa::alpha_default );
725  }
726  else
727  {
728  vpRGBa rgbaVal;
729  rgbaVal.A = vpRGBa::alpha_default;
730  for ( unsigned int i = 0; i < dest.getRows(); ++i )
731  {
732  for ( unsigned int j = 0; j < dest.getCols(); ++j )
733  {
734  cv::Vec3b tmp = src.at< cv::Vec3b >( (int)i, (int)j );
735  rgbaVal.R = tmp[2];
736  rgbaVal.G = tmp[1];
737  rgbaVal.B = tmp[0];
738  if ( flip )
739  {
740  dest[dest.getRows() - i - 1][j] = rgbaVal;
741  }
742  else
743  {
744  dest[i][j] = rgbaVal;
745  }
746  }
747  }
748  }
749  }
750  else if ( src.type() == CV_8UC1 )
751  {
752  if ( src.isContinuous() && !flip )
753  {
754  SimdGrayToBgra( src.data, src.cols, src.rows, src.step[0], reinterpret_cast< uint8_t * >( dest.bitmap ),
755  dest.getWidth() * sizeof( vpRGBa ), vpRGBa::alpha_default );
756  }
757  else
758  {
759  vpRGBa rgbaVal;
760  for ( unsigned int i = 0; i < dest.getRows(); ++i )
761  {
762  for ( unsigned int j = 0; j < dest.getCols(); ++j )
763  {
764  rgbaVal = src.at< unsigned char >( (int)i, (int)j );
765  if ( flip )
766  {
767  dest[dest.getRows() - i - 1][j] = rgbaVal;
768  }
769  else
770  {
771  dest[i][j] = rgbaVal;
772  }
773  }
774  }
775  }
776  }
777 }
778 
821 void
822 vpImageConvert::convert( const cv::Mat &src, vpImage< unsigned char > &dest, bool flip, unsigned int nThreads )
823 {
824  if ( src.type() == CV_8UC1 )
825  {
826  dest.resize( (unsigned int)src.rows, (unsigned int)src.cols );
827  if ( src.isContinuous() && !flip )
828  {
829  memcpy( dest.bitmap, src.data, ( size_t )( src.rows * src.cols ) );
830  }
831  else
832  {
833  if ( flip )
834  {
835  for ( unsigned int i = 0; i < dest.getRows(); ++i )
836  {
837  memcpy( dest.bitmap + i * dest.getCols(), src.data + ( dest.getRows() - i - 1 ) * src.step1(),
838  (size_t)src.step );
839  }
840  }
841  else
842  {
843  for ( unsigned int i = 0; i < dest.getRows(); ++i )
844  {
845  memcpy( dest.bitmap + i * dest.getCols(), src.data + i * src.step1(), (size_t)src.step );
846  }
847  }
848  }
849  }
850  else if ( src.type() == CV_8UC3 )
851  {
852  dest.resize( (unsigned int)src.rows, (unsigned int)src.cols );
853  if ( src.isContinuous() )
854  {
855  BGRToGrey( (unsigned char *)src.data, (unsigned char *)dest.bitmap, (unsigned int)src.cols,
856  (unsigned int)src.rows, flip, nThreads );
857  }
858  else
859  {
860  if ( flip )
861  {
862  for ( unsigned int i = 0; i < dest.getRows(); ++i )
863  {
864  BGRToGrey( (unsigned char *)src.data + i * src.step1(),
865  (unsigned char *)dest.bitmap + ( dest.getRows() - i - 1 ) * dest.getCols(),
866  (unsigned int)dest.getCols(), 1, false );
867  }
868  }
869  else
870  {
871  for ( unsigned int i = 0; i < dest.getRows(); ++i )
872  {
873  BGRToGrey( (unsigned char *)src.data + i * src.step1(), (unsigned char *)dest.bitmap + i * dest.getCols(),
874  (unsigned int)dest.getCols(), 1, false );
875  }
876  }
877  }
878  }
879  else if ( src.type() == CV_8UC4 )
880  {
881  dest.resize( (unsigned int)src.rows, (unsigned int)src.cols );
882  if ( src.isContinuous() )
883  {
884  BGRaToGrey( (unsigned char *)src.data, (unsigned char *)dest.bitmap, (unsigned int)src.cols,
885  (unsigned int)src.rows, flip, nThreads );
886  }
887  else
888  {
889  if ( flip )
890  {
891  for ( unsigned int i = 0; i < dest.getRows(); ++i )
892  {
893  BGRaToGrey( (unsigned char *)src.data + i * src.step1(),
894  (unsigned char *)dest.bitmap + ( dest.getRows() - i - 1 ) * dest.getCols(),
895  (unsigned int)dest.getCols(), 1, false );
896  }
897  }
898  else
899  {
900  for ( unsigned int i = 0; i < dest.getRows(); ++i )
901  {
902  BGRaToGrey( (unsigned char *)src.data + i * src.step1(), (unsigned char *)dest.bitmap + i * dest.getCols(),
903  (unsigned int)dest.getCols(), 1, false );
904  }
905  }
906  }
907  }
908 }
909 
946 void
947 vpImageConvert::convert( const vpImage< vpRGBa > &src, cv::Mat &dest )
948 {
949  cv::Mat vpToMat( (int)src.getRows(), (int)src.getCols(), CV_8UC4, (void *)src.bitmap );
950  cv::cvtColor( vpToMat, dest, cv::COLOR_RGBA2BGR );
951 }
952 
991 void
992 vpImageConvert::convert( const vpImage< unsigned char > &src, cv::Mat &dest, bool copyData )
993 {
994  if ( copyData )
995  {
996  cv::Mat tmpMap( (int)src.getRows(), (int)src.getCols(), CV_8UC1, (void *)src.bitmap );
997  dest = tmpMap.clone();
998  }
999  else
1000  {
1001  dest = cv::Mat( (int)src.getRows(), (int)src.getCols(), CV_8UC1, (void *)src.bitmap );
1002  }
1003 }
1004 
1005 #endif
1006 #endif
1007 
1008 #ifdef VISP_HAVE_YARP
1009 
1042 void
1043 vpImageConvert::convert( const vpImage< unsigned char > &src, yarp::sig::ImageOf< yarp::sig::PixelMono > *dest,
1044  bool copyData )
1045 {
1046  if ( copyData )
1047  {
1048  dest->resize( src.getWidth(), src.getHeight() );
1049  memcpy( dest->getRawImage(), src.bitmap, src.getHeight() * src.getWidth() );
1050  }
1051  else
1052  dest->setExternal( src.bitmap, (int)src.getCols(), (int)src.getRows() );
1053 }
1054 
1093 void
1094 vpImageConvert::convert( const yarp::sig::ImageOf< yarp::sig::PixelMono > *src, vpImage< unsigned char > &dest,
1095  bool copyData )
1096 {
1097  dest.resize( src->height(), src->width() );
1098  if ( copyData )
1099  memcpy( dest.bitmap, src->getRawImage(), src->height() * src->width() * sizeof( yarp::sig::PixelMono ) );
1100  else
1101  dest.bitmap = src->getRawImage();
1102 }
1103 
1138 void
1139 vpImageConvert::convert( const vpImage< vpRGBa > &src, yarp::sig::ImageOf< yarp::sig::PixelRgba > *dest, bool copyData )
1140 {
1141  if ( copyData )
1142  {
1143  dest->resize( src.getWidth(), src.getHeight() );
1144  memcpy( dest->getRawImage(), src.bitmap, src.getHeight() * src.getWidth() * sizeof( vpRGBa ) );
1145  }
1146  else
1147  dest->setExternal( src.bitmap, (int)src.getCols(), (int)src.getRows() );
1148 }
1149 
1188 void
1189 vpImageConvert::convert( const yarp::sig::ImageOf< yarp::sig::PixelRgba > *src, vpImage< vpRGBa > &dest, bool copyData )
1190 {
1191  dest.resize( src->height(), src->width() );
1192  if ( copyData )
1193  memcpy( dest.bitmap, src->getRawImage(), src->height() * src->width() * sizeof( yarp::sig::PixelRgba ) );
1194  else
1195  dest.bitmap = static_cast< vpRGBa * >( src->getRawImage() );
1196 }
1197 
1230 void
1231 vpImageConvert::convert( const vpImage< vpRGBa > &src, yarp::sig::ImageOf< yarp::sig::PixelRgb > *dest )
1232 {
1233  dest->resize( src.getWidth(), src.getHeight() );
1234  for ( unsigned int i = 0; i < src.getRows(); i++ )
1235  {
1236  for ( unsigned int j = 0; j < src.getWidth(); j++ )
1237  {
1238  dest->pixel( j, i ).r = src[i][j].R;
1239  dest->pixel( j, i ).g = src[i][j].G;
1240  dest->pixel( j, i ).b = src[i][j].B;
1241  }
1242  }
1243 }
1244 
1283 void
1284 vpImageConvert::convert( const yarp::sig::ImageOf< yarp::sig::PixelRgb > *src, vpImage< vpRGBa > &dest )
1285 {
1286  dest.resize( src->height(), src->width() );
1287  for ( int i = 0; i < src->height(); i++ )
1288  {
1289  for ( int j = 0; j < src->width(); j++ )
1290  {
1291  dest[i][j].R = src->pixel( j, i ).r;
1292  dest[i][j].G = src->pixel( j, i ).g;
1293  dest[i][j].B = src->pixel( j, i ).b;
1294  dest[i][j].A = vpRGBa::alpha_default;
1295  }
1296  }
1297 }
1298 
1299 #endif
1300 
1301 #define vpSAT( c ) \
1302  if ( c & ( ~255 ) ) \
1303  { \
1304  if ( c < 0 ) \
1305  c = 0; \
1306  else \
1307  c = 255; \
1308  }
1309 
1321 void
1322 vpImageConvert::YUYVToRGBa( unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height )
1323 {
1324  unsigned char *s;
1325  unsigned char *d;
1326  int w, h;
1327  int r, g, b, cr, cg, cb, y1, y2;
1328 
1329  h = (int)height;
1330  w = (int)width;
1331  s = yuyv;
1332  d = rgba;
1333  while ( h-- )
1334  {
1335  int c = w >> 1;
1336  while ( c-- )
1337  {
1338  y1 = *s++;
1339  cb = ( ( *s - 128 ) * 454 ) >> 8;
1340  cg = ( *s++ - 128 ) * 88;
1341  y2 = *s++;
1342  cr = ( ( *s - 128 ) * 359 ) >> 8;
1343  cg = ( cg + ( *s++ - 128 ) * 183 ) >> 8;
1344 
1345  r = y1 + cr;
1346  b = y1 + cb;
1347  g = y1 - cg;
1348  vpSAT( r ) vpSAT( g ) vpSAT( b )
1349 
1350  *d++ = static_cast< unsigned char >( r );
1351  *d++ = static_cast< unsigned char >( g );
1352  *d++ = static_cast< unsigned char >( b );
1353  *d++ = vpRGBa::alpha_default;
1354 
1355  r = y2 + cr;
1356  b = y2 + cb;
1357  g = y2 - cg;
1358  vpSAT( r ) vpSAT( g ) vpSAT( b )
1359 
1360  *d++ = static_cast< unsigned char >( r );
1361  *d++ = static_cast< unsigned char >( g );
1362  *d++ = static_cast< unsigned char >( b );
1363  *d++ = vpRGBa::alpha_default;
1364  }
1365  }
1366 }
1367 
1378 void
1379 vpImageConvert::YUYVToRGB( unsigned char *yuyv, unsigned char *rgb, unsigned int width, unsigned int height )
1380 {
1381  unsigned char *s;
1382  unsigned char *d;
1383  int h, w;
1384  int r, g, b, cr, cg, cb, y1, y2;
1385 
1386  h = (int)height;
1387  w = (int)width;
1388  s = yuyv;
1389  d = rgb;
1390  while ( h-- )
1391  {
1392  int c = w >> 1;
1393  while ( c-- )
1394  {
1395  y1 = *s++;
1396  cb = ( ( *s - 128 ) * 454 ) >> 8;
1397  cg = ( *s++ - 128 ) * 88;
1398  y2 = *s++;
1399  cr = ( ( *s - 128 ) * 359 ) >> 8;
1400  cg = ( cg + ( *s++ - 128 ) * 183 ) >> 8;
1401 
1402  r = y1 + cr;
1403  b = y1 + cb;
1404  g = y1 - cg;
1405  vpSAT( r ) vpSAT( g ) vpSAT( b )
1406 
1407  *d++ = static_cast< unsigned char >( r );
1408  *d++ = static_cast< unsigned char >( g );
1409  *d++ = static_cast< unsigned char >( b );
1410 
1411  r = y2 + cr;
1412  b = y2 + cb;
1413  g = y2 - cg;
1414  vpSAT( r ) vpSAT( g ) vpSAT( b )
1415 
1416  *d++ = static_cast< unsigned char >( r );
1417  *d++ = static_cast< unsigned char >( g );
1418  *d++ = static_cast< unsigned char >( b );
1419  }
1420  }
1421 }
1422 
1433 void
1434 vpImageConvert::YUYVToGrey( unsigned char *yuyv, unsigned char *grey, unsigned int size )
1435 {
1436  unsigned int i = 0, j = 0;
1437 
1438  while ( j < size * 2 )
1439  {
1440  grey[i++] = yuyv[j];
1441  grey[i++] = yuyv[j + 2];
1442  j += 4;
1443  }
1444 }
1445 
1455 void
1456 vpImageConvert::YUV411ToRGBa( unsigned char *yuv, unsigned char *rgba, unsigned int size )
1457 {
1458 #if 1
1459  // std::cout << "call optimized ConvertYUV411ToRGBa()" << std::endl;
1460  for ( unsigned int i = size / 4; i; i-- )
1461  {
1462  int U = (int)( ( *yuv++ - 128 ) * 0.354 );
1463  int U5 = 5 * U;
1464  int Y0 = *yuv++;
1465  int Y1 = *yuv++;
1466  int V = (int)( ( *yuv++ - 128 ) * 0.707 );
1467  int V2 = 2 * V;
1468  int Y2 = *yuv++;
1469  int Y3 = *yuv++;
1470  int UV = -U - V;
1471 
1472  // Original equations
1473  // R = Y + 1.402 V
1474  // G = Y - 0.344 U - 0.714 V
1475  // B = Y + 1.772 U
1476  int R = Y0 + V2;
1477  if ( ( R >> 8 ) > 0 )
1478  R = 255;
1479  else if ( R < 0 )
1480  R = 0;
1481 
1482  int G = Y0 + UV;
1483  if ( ( G >> 8 ) > 0 )
1484  G = 255;
1485  else if ( G < 0 )
1486  G = 0;
1487 
1488  int B = Y0 + U5;
1489  if ( ( B >> 8 ) > 0 )
1490  B = 255;
1491  else if ( B < 0 )
1492  B = 0;
1493 
1494  *rgba++ = (unsigned char)R;
1495  *rgba++ = (unsigned char)G;
1496  *rgba++ = (unsigned char)B;
1497  *rgba++ = vpRGBa::alpha_default;
1498 
1499  //---
1500  R = Y1 + V2;
1501  if ( ( R >> 8 ) > 0 )
1502  R = 255;
1503  else if ( R < 0 )
1504  R = 0;
1505 
1506  G = Y1 + UV;
1507  if ( ( G >> 8 ) > 0 )
1508  G = 255;
1509  else if ( G < 0 )
1510  G = 0;
1511 
1512  B = Y1 + U5;
1513  if ( ( B >> 8 ) > 0 )
1514  B = 255;
1515  else if ( B < 0 )
1516  B = 0;
1517 
1518  *rgba++ = (unsigned char)R;
1519  *rgba++ = (unsigned char)G;
1520  *rgba++ = (unsigned char)B;
1521  *rgba++ = vpRGBa::alpha_default;
1522 
1523  //---
1524  R = Y2 + V2;
1525  if ( ( R >> 8 ) > 0 )
1526  R = 255;
1527  else if ( R < 0 )
1528  R = 0;
1529 
1530  G = Y2 + UV;
1531  if ( ( G >> 8 ) > 0 )
1532  G = 255;
1533  else if ( G < 0 )
1534  G = 0;
1535 
1536  B = Y2 + U5;
1537  if ( ( B >> 8 ) > 0 )
1538  B = 255;
1539  else if ( B < 0 )
1540  B = 0;
1541 
1542  *rgba++ = (unsigned char)R;
1543  *rgba++ = (unsigned char)G;
1544  *rgba++ = (unsigned char)B;
1545  *rgba++ = vpRGBa::alpha_default;
1546 
1547  //---
1548  R = Y3 + V2;
1549  if ( ( R >> 8 ) > 0 )
1550  R = 255;
1551  else if ( R < 0 )
1552  R = 0;
1553 
1554  G = Y3 + UV;
1555  if ( ( G >> 8 ) > 0 )
1556  G = 255;
1557  else if ( G < 0 )
1558  G = 0;
1559 
1560  B = Y3 + U5;
1561  if ( ( B >> 8 ) > 0 )
1562  B = 255;
1563  else if ( B < 0 )
1564  B = 0;
1565 
1566  *rgba++ = (unsigned char)R;
1567  *rgba++ = (unsigned char)G;
1568  *rgba++ = (unsigned char)B;
1569  *rgba++ = vpRGBa::alpha_default;
1570  }
1571 #else
1572  // tres tres lent ....
1573  unsigned int i = 0, j = 0;
1574  unsigned char r, g, b;
1575  while ( j < numpixels * 3 / 2 )
1576  {
1577 
1578  YUVToRGB( yuv[j + 1], yuv[j], yuv[j + 3], r, g, b );
1579  rgba[i] = r;
1580  rgba[i + 1] = g;
1581  rgba[i + 2] = b;
1582  rgba[i + 3] = vpRGBa::alpha_default;
1583  i += 4;
1584 
1585  YUVToRGB( yuv[j + 2], yuv[j], yuv[j + 3], r, g, b );
1586  rgba[i] = r;
1587  rgba[i + 1] = g;
1588  rgba[i + 2] = b;
1589  rgba[i + 3] = vpRGBa::alpha_default;
1590  i += 4;
1591 
1592  YUVToRGB( yuv[j + 4], yuv[j], yuv[j + 3], r, g, b );
1593  rgba[i] = r;
1594  rgba[i + 1] = g;
1595  rgba[i + 2] = b;
1596  rgba[i + 3] = vpRGBa::alpha_default;
1597  i += 4;
1598 
1599  YUVToRGB( yuv[j + 5], yuv[j], yuv[j + 3], r, g, b );
1600  rgba[i] = r;
1601  rgba[i + 1] = g;
1602  rgba[i + 2] = b;
1603  rgba[i + 3] = vpRGBa::alpha_default;
1604  i += 4;
1605 
1606  j += 6;
1607  }
1608 #endif
1609 }
1610 
1623 void
1624 vpImageConvert::YUV422ToRGBa( unsigned char *yuv, unsigned char *rgba, unsigned int size )
1625 {
1626 
1627 #if 1
1628  // std::cout << "call optimized convertYUV422ToRGBa()" << std::endl;
1629  for ( unsigned int i = size / 2; i; i-- )
1630  {
1631  int U = (int)( ( *yuv++ - 128 ) * 0.354 );
1632  int U5 = 5 * U;
1633  int Y0 = *yuv++;
1634  int V = (int)( ( *yuv++ - 128 ) * 0.707 );
1635  int V2 = 2 * V;
1636  int Y1 = *yuv++;
1637  int UV = -U - V;
1638 
1639  //---
1640  int R = Y0 + V2;
1641  if ( ( R >> 8 ) > 0 )
1642  R = 255;
1643  else if ( R < 0 )
1644  R = 0;
1645 
1646  int G = Y0 + UV;
1647  if ( ( G >> 8 ) > 0 )
1648  G = 255;
1649  else if ( G < 0 )
1650  G = 0;
1651 
1652  int B = Y0 + U5;
1653  if ( ( B >> 8 ) > 0 )
1654  B = 255;
1655  else if ( B < 0 )
1656  B = 0;
1657 
1658  *rgba++ = (unsigned char)R;
1659  *rgba++ = (unsigned char)G;
1660  *rgba++ = (unsigned char)B;
1661  *rgba++ = vpRGBa::alpha_default;
1662 
1663  //---
1664  R = Y1 + V2;
1665  if ( ( R >> 8 ) > 0 )
1666  R = 255;
1667  else if ( R < 0 )
1668  R = 0;
1669 
1670  G = Y1 + UV;
1671  if ( ( G >> 8 ) > 0 )
1672  G = 255;
1673  else if ( G < 0 )
1674  G = 0;
1675 
1676  B = Y1 + U5;
1677  if ( ( B >> 8 ) > 0 )
1678  B = 255;
1679  else if ( B < 0 )
1680  B = 0;
1681 
1682  *rgba++ = (unsigned char)R;
1683  *rgba++ = (unsigned char)G;
1684  *rgba++ = (unsigned char)B;
1685  *rgba++ = vpRGBa::alpha_default;
1686  }
1687 
1688 #else
1689  // tres tres lent ....
1690  unsigned int i = 0, j = 0;
1691  unsigned char r, g, b;
1692 
1693  while ( j < size * 2 )
1694  {
1695 
1696  YUVToRGB( yuv[j + 1], yuv[j], yuv[j + 2], r, g, b );
1697  rgba[i] = r;
1698  rgba[i + 1] = g;
1699  rgba[i + 2] = b;
1700  rgba[i + 3] = vpRGBa::alpha_default;
1701  i += 4;
1702 
1703  YUVToRGB( yuv[j + 3], yuv[j], yuv[j + 2], r, g, b );
1704  rgba[i] = r;
1705  rgba[i + 1] = g;
1706  rgba[i + 2] = b;
1707  rgba[i + 3] = vpRGBa::alpha_default;
1708  i += 4;
1709  j += 4;
1710  }
1711 #endif
1712 }
1713 
1722 void
1723 vpImageConvert::YUV411ToGrey( unsigned char *yuv, unsigned char *grey, unsigned int size )
1724 {
1725  unsigned int i = 0, j = 0;
1726  while ( j < size * 3 / 2 )
1727  {
1728  grey[i] = yuv[j + 1];
1729  grey[i + 1] = yuv[j + 2];
1730  grey[i + 2] = yuv[j + 4];
1731  grey[i + 3] = yuv[j + 5];
1732 
1733  i += 4;
1734 
1735  j += 6;
1736  }
1737 }
1738 
1749 void
1750 vpImageConvert::YUV422ToRGB( unsigned char *yuv, unsigned char *rgb, unsigned int size )
1751 {
1752 #if 1
1753  // std::cout << "call optimized convertYUV422ToRGB()" << std::endl;
1754  for ( unsigned int i = size / 2; i; i-- )
1755  {
1756  int U = (int)( ( *yuv++ - 128 ) * 0.354 );
1757  int U5 = 5 * U;
1758  int Y0 = *yuv++;
1759  int V = (int)( ( *yuv++ - 128 ) * 0.707 );
1760  int V2 = 2 * V;
1761  int Y1 = *yuv++;
1762  int UV = -U - V;
1763 
1764  //---
1765  int R = Y0 + V2;
1766  if ( ( R >> 8 ) > 0 )
1767  R = 255;
1768  else if ( R < 0 )
1769  R = 0;
1770 
1771  int G = Y0 + UV;
1772  if ( ( G >> 8 ) > 0 )
1773  G = 255;
1774  else if ( G < 0 )
1775  G = 0;
1776 
1777  int B = Y0 + U5;
1778  if ( ( B >> 8 ) > 0 )
1779  B = 255;
1780  else if ( B < 0 )
1781  B = 0;
1782 
1783  *rgb++ = (unsigned char)R;
1784  *rgb++ = (unsigned char)G;
1785  *rgb++ = (unsigned char)B;
1786 
1787  //---
1788  R = Y1 + V2;
1789  if ( ( R >> 8 ) > 0 )
1790  R = 255;
1791  else if ( R < 0 )
1792  R = 0;
1793 
1794  G = Y1 + UV;
1795  if ( ( G >> 8 ) > 0 )
1796  G = 255;
1797  else if ( G < 0 )
1798  G = 0;
1799 
1800  B = Y1 + U5;
1801  if ( ( B >> 8 ) > 0 )
1802  B = 255;
1803  else if ( B < 0 )
1804  B = 0;
1805 
1806  *rgb++ = (unsigned char)R;
1807  *rgb++ = (unsigned char)G;
1808  *rgb++ = (unsigned char)B;
1809  }
1810 
1811 #else
1812  // tres tres lent ....
1813  unsigned int i = 0, j = 0;
1814  unsigned char r, g, b;
1815 
1816  while ( j < size * 2 )
1817  {
1818 
1819  YUVToRGB( yuv[j + 1], yuv[j], yuv[j + 2], r, g, b );
1820  rgb[i] = r;
1821  rgb[i + 1] = g;
1822  rgb[i + 2] = b;
1823  i += 3;
1824 
1825  YUVToRGB( yuv[j + 3], yuv[j], yuv[j + 2], r, g, b );
1826  rgb[i] = r;
1827  rgb[i + 1] = g;
1828  rgb[i + 2] = b;
1829  i += 3;
1830  j += 4;
1831  }
1832 #endif
1833 }
1834 
1845 void
1846 vpImageConvert::YUV422ToGrey( unsigned char *yuv, unsigned char *grey, unsigned int size )
1847 {
1848  unsigned int i = 0, j = 0;
1849 
1850  while ( j < size * 2 )
1851  {
1852  grey[i++] = yuv[j + 1];
1853  grey[i++] = yuv[j + 3];
1854  j += 4;
1855  }
1856 }
1857 
1866 void
1867 vpImageConvert::YUV411ToRGB( unsigned char *yuv, unsigned char *rgb, unsigned int size )
1868 {
1869 #if 1
1870  // std::cout << "call optimized ConvertYUV411ToRGB()" << std::endl;
1871  for ( unsigned int i = size / 4; i; i-- )
1872  {
1873  int U = (int)( ( *yuv++ - 128 ) * 0.354 );
1874  int U5 = 5 * U;
1875  int Y0 = *yuv++;
1876  int Y1 = *yuv++;
1877  int V = (int)( ( *yuv++ - 128 ) * 0.707 );
1878  int V2 = 2 * V;
1879  int Y2 = *yuv++;
1880  int Y3 = *yuv++;
1881  int UV = -U - V;
1882 
1883  // Original equations
1884  // R = Y + 1.402 V
1885  // G = Y - 0.344 U - 0.714 V
1886  // B = Y + 1.772 U
1887  int R = Y0 + V2;
1888  if ( ( R >> 8 ) > 0 )
1889  R = 255;
1890  else if ( R < 0 )
1891  R = 0;
1892 
1893  int G = Y0 + UV;
1894  if ( ( G >> 8 ) > 0 )
1895  G = 255;
1896  else if ( G < 0 )
1897  G = 0;
1898 
1899  int B = Y0 + U5;
1900  if ( ( B >> 8 ) > 0 )
1901  B = 255;
1902  else if ( B < 0 )
1903  B = 0;
1904 
1905  *rgb++ = (unsigned char)R;
1906  *rgb++ = (unsigned char)G;
1907  *rgb++ = (unsigned char)B;
1908 
1909  //---
1910  R = Y1 + V2;
1911  if ( ( R >> 8 ) > 0 )
1912  R = 255;
1913  else if ( R < 0 )
1914  R = 0;
1915 
1916  G = Y1 + UV;
1917  if ( ( G >> 8 ) > 0 )
1918  G = 255;
1919  else if ( G < 0 )
1920  G = 0;
1921 
1922  B = Y1 + U5;
1923  if ( ( B >> 8 ) > 0 )
1924  B = 255;
1925  else if ( B < 0 )
1926  B = 0;
1927 
1928  *rgb++ = (unsigned char)R;
1929  *rgb++ = (unsigned char)G;
1930  *rgb++ = (unsigned char)B;
1931 
1932  //---
1933  R = Y2 + V2;
1934  if ( ( R >> 8 ) > 0 )
1935  R = 255;
1936  else if ( R < 0 )
1937  R = 0;
1938 
1939  G = Y2 + UV;
1940  if ( ( G >> 8 ) > 0 )
1941  G = 255;
1942  else if ( G < 0 )
1943  G = 0;
1944 
1945  B = Y2 + U5;
1946  if ( ( B >> 8 ) > 0 )
1947  B = 255;
1948  else if ( B < 0 )
1949  B = 0;
1950 
1951  *rgb++ = (unsigned char)R;
1952  *rgb++ = (unsigned char)G;
1953  *rgb++ = (unsigned char)B;
1954 
1955  //---
1956  R = Y3 + V2;
1957  if ( ( R >> 8 ) > 0 )
1958  R = 255;
1959  else if ( R < 0 )
1960  R = 0;
1961 
1962  G = Y3 + UV;
1963  if ( ( G >> 8 ) > 0 )
1964  G = 255;
1965  else if ( G < 0 )
1966  G = 0;
1967 
1968  B = Y3 + U5;
1969  if ( ( B >> 8 ) > 0 )
1970  B = 255;
1971  else if ( B < 0 )
1972  B = 0;
1973 
1974  *rgb++ = (unsigned char)R;
1975  *rgb++ = (unsigned char)G;
1976  *rgb++ = (unsigned char)B;
1977  }
1978 #else
1979  // tres tres lent ....
1980 
1981  unsigned int i = 0, j = 0;
1982  unsigned char r, g, b;
1983 
1984  while ( j < size * 3 / 2 )
1985  {
1986  YUVToRGB( yuv[j + 1], yuv[j], yuv[j + 3], r, g, b );
1987  rgb[i] = r;
1988  rgb[i + 1] = g;
1989  rgb[i + 2] = b;
1990  i += 3;
1991 
1992  YUVToRGB( yuv[j + 2], yuv[j], yuv[j + 3], r, g, b );
1993  rgb[i] = r;
1994  rgb[i + 1] = g;
1995  rgb[i + 2] = b;
1996  i += 3;
1997 
1998  YUVToRGB( yuv[j + 4], yuv[j], yuv[j + 3], r, g, b );
1999  rgb[i] = r;
2000  rgb[i + 1] = g;
2001  rgb[i + 2] = b;
2002  i += 3;
2003 
2004  YUVToRGB( yuv[j + 5], yuv[j], yuv[j + 3], r, g, b );
2005  rgb[i] = r;
2006  rgb[i + 1] = g;
2007  rgb[i + 2] = b;
2008  i += 3;
2009  // TRACE("r= %d g=%d b=%d", r, g, b);
2010 
2011  j += 6;
2012  }
2013 #endif
2014 }
2015 
2026 void
2027 vpImageConvert::YUV420ToRGBa( unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height )
2028 {
2029  // std::cout << "call optimized ConvertYUV420ToRGBa()" << std::endl;
2030  int U, V, R, G, B, V2, U5, UV;
2031  int Y0, Y1, Y2, Y3;
2032  unsigned int size = width * height;
2033  unsigned char *iU = yuv + size;
2034  unsigned char *iV = yuv + 5 * size / 4;
2035  for ( unsigned int i = 0; i < height / 2; i++ )
2036  {
2037  for ( unsigned int j = 0; j < width / 2; j++ )
2038  {
2039  U = (int)( ( *iU++ - 128 ) * 0.354 );
2040  U5 = 5 * U;
2041  V = (int)( ( *iV++ - 128 ) * 0.707 );
2042  V2 = 2 * V;
2043  UV = -U - V;
2044  Y0 = *yuv++;
2045  Y1 = *yuv;
2046  yuv = yuv + width - 1;
2047  Y2 = *yuv++;
2048  Y3 = *yuv;
2049  yuv = yuv - width + 1;
2050 
2051  // Original equations
2052  // R = Y + 1.402 V
2053  // G = Y - 0.344 U - 0.714 V
2054  // B = Y + 1.772 U
2055  R = Y0 + V2;
2056  if ( ( R >> 8 ) > 0 )
2057  R = 255;
2058  else if ( R < 0 )
2059  R = 0;
2060 
2061  G = Y0 + UV;
2062  if ( ( G >> 8 ) > 0 )
2063  G = 255;
2064  else if ( G < 0 )
2065  G = 0;
2066 
2067  B = Y0 + U5;
2068  if ( ( B >> 8 ) > 0 )
2069  B = 255;
2070  else if ( B < 0 )
2071  B = 0;
2072 
2073  *rgba++ = (unsigned char)R;
2074  *rgba++ = (unsigned char)G;
2075  *rgba++ = (unsigned char)B;
2076  *rgba++ = vpRGBa::alpha_default;
2077 
2078  //---
2079  R = Y1 + V2;
2080  if ( ( R >> 8 ) > 0 )
2081  R = 255;
2082  else if ( R < 0 )
2083  R = 0;
2084 
2085  G = Y1 + UV;
2086  if ( ( G >> 8 ) > 0 )
2087  G = 255;
2088  else if ( G < 0 )
2089  G = 0;
2090 
2091  B = Y1 + U5;
2092  if ( ( B >> 8 ) > 0 )
2093  B = 255;
2094  else if ( B < 0 )
2095  B = 0;
2096 
2097  *rgba++ = (unsigned char)R;
2098  *rgba++ = (unsigned char)G;
2099  *rgba++ = (unsigned char)B;
2100  *rgba = vpRGBa::alpha_default;
2101  rgba = rgba + 4 * width - 7;
2102 
2103  //---
2104  R = Y2 + V2;
2105  if ( ( R >> 8 ) > 0 )
2106  R = 255;
2107  else if ( R < 0 )
2108  R = 0;
2109 
2110  G = Y2 + UV;
2111  if ( ( G >> 8 ) > 0 )
2112  G = 255;
2113  else if ( G < 0 )
2114  G = 0;
2115 
2116  B = Y2 + U5;
2117  if ( ( B >> 8 ) > 0 )
2118  B = 255;
2119  else if ( B < 0 )
2120  B = 0;
2121 
2122  *rgba++ = (unsigned char)R;
2123  *rgba++ = (unsigned char)G;
2124  *rgba++ = (unsigned char)B;
2125  *rgba++ = vpRGBa::alpha_default;
2126 
2127  //---
2128  R = Y3 + V2;
2129  if ( ( R >> 8 ) > 0 )
2130  R = 255;
2131  else if ( R < 0 )
2132  R = 0;
2133 
2134  G = Y3 + UV;
2135  if ( ( G >> 8 ) > 0 )
2136  G = 255;
2137  else if ( G < 0 )
2138  G = 0;
2139 
2140  B = Y3 + U5;
2141  if ( ( B >> 8 ) > 0 )
2142  B = 255;
2143  else if ( B < 0 )
2144  B = 0;
2145 
2146  *rgba++ = (unsigned char)R;
2147  *rgba++ = (unsigned char)G;
2148  *rgba++ = (unsigned char)B;
2149  *rgba = vpRGBa::alpha_default;
2150  rgba = rgba - 4 * width + 1;
2151  }
2152  yuv += width;
2153  rgba += 4 * width;
2154  }
2155 }
2156 
2165 void
2166 vpImageConvert::YUV420ToRGB( unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height )
2167 {
2168  // std::cout << "call optimized ConvertYUV420ToRGB()" << std::endl;
2169  int U, V, R, G, B, V2, U5, UV;
2170  int Y0, Y1, Y2, Y3;
2171  unsigned int size = width * height;
2172  unsigned char *iU = yuv + size;
2173  unsigned char *iV = yuv + 5 * size / 4;
2174  for ( unsigned int i = 0; i < height / 2; i++ )
2175  {
2176  for ( unsigned int j = 0; j < width / 2; j++ )
2177  {
2178  U = (int)( ( *iU++ - 128 ) * 0.354 );
2179  U5 = 5 * U;
2180  V = (int)( ( *iV++ - 128 ) * 0.707 );
2181  V2 = 2 * V;
2182  UV = -U - V;
2183  Y0 = *yuv++;
2184  Y1 = *yuv;
2185  yuv = yuv + width - 1;
2186  Y2 = *yuv++;
2187  Y3 = *yuv;
2188  yuv = yuv - width + 1;
2189 
2190  // Original equations
2191  // R = Y + 1.402 V
2192  // G = Y - 0.344 U - 0.714 V
2193  // B = Y + 1.772 U
2194  R = Y0 + V2;
2195  if ( ( R >> 8 ) > 0 )
2196  R = 255;
2197  else if ( R < 0 )
2198  R = 0;
2199 
2200  G = Y0 + UV;
2201  if ( ( G >> 8 ) > 0 )
2202  G = 255;
2203  else if ( G < 0 )
2204  G = 0;
2205 
2206  B = Y0 + U5;
2207  if ( ( B >> 8 ) > 0 )
2208  B = 255;
2209  else if ( B < 0 )
2210  B = 0;
2211 
2212  *rgb++ = (unsigned char)R;
2213  *rgb++ = (unsigned char)G;
2214  *rgb++ = (unsigned char)B;
2215 
2216  //---
2217  R = Y1 + V2;
2218  if ( ( R >> 8 ) > 0 )
2219  R = 255;
2220  else if ( R < 0 )
2221  R = 0;
2222 
2223  G = Y1 + UV;
2224  if ( ( G >> 8 ) > 0 )
2225  G = 255;
2226  else if ( G < 0 )
2227  G = 0;
2228 
2229  B = Y1 + U5;
2230  if ( ( B >> 8 ) > 0 )
2231  B = 255;
2232  else if ( B < 0 )
2233  B = 0;
2234 
2235  *rgb++ = (unsigned char)R;
2236  *rgb++ = (unsigned char)G;
2237  *rgb = (unsigned char)B;
2238  rgb = rgb + 3 * width - 5;
2239 
2240  //---
2241  R = Y2 + V2;
2242  if ( ( R >> 8 ) > 0 )
2243  R = 255;
2244  else if ( R < 0 )
2245  R = 0;
2246 
2247  G = Y2 + UV;
2248  if ( ( G >> 8 ) > 0 )
2249  G = 255;
2250  else if ( G < 0 )
2251  G = 0;
2252 
2253  B = Y2 + U5;
2254  if ( ( B >> 8 ) > 0 )
2255  B = 255;
2256  else if ( B < 0 )
2257  B = 0;
2258 
2259  *rgb++ = (unsigned char)R;
2260  *rgb++ = (unsigned char)G;
2261  *rgb++ = (unsigned char)B;
2262 
2263  //---
2264  R = Y3 + V2;
2265  if ( ( R >> 8 ) > 0 )
2266  R = 255;
2267  else if ( R < 0 )
2268  R = 0;
2269 
2270  G = Y3 + UV;
2271  if ( ( G >> 8 ) > 0 )
2272  G = 255;
2273  else if ( G < 0 )
2274  G = 0;
2275 
2276  B = Y3 + U5;
2277  if ( ( B >> 8 ) > 0 )
2278  B = 255;
2279  else if ( B < 0 )
2280  B = 0;
2281 
2282  *rgb++ = (unsigned char)R;
2283  *rgb++ = (unsigned char)G;
2284  *rgb = (unsigned char)B;
2285  rgb = rgb - 3 * width + 1;
2286  }
2287  yuv += width;
2288  rgb += 3 * width;
2289  }
2290 }
2291 
2299 void
2300 vpImageConvert::YUV420ToGrey( unsigned char *yuv, unsigned char *grey, unsigned int size )
2301 {
2302  for ( unsigned int i = 0; i < size; i++ )
2303  {
2304  *grey++ = *yuv++;
2305  }
2306 }
2307 
2317 void
2318 vpImageConvert::YUV444ToRGBa( unsigned char *yuv, unsigned char *rgba, unsigned int size )
2319 {
2320  for ( unsigned int i = 0; i < size; i++ )
2321  {
2322  int U = (int)( ( *yuv++ - 128 ) * 0.354 );
2323  int U5 = 5 * U;
2324  int Y = *yuv++;
2325  int V = (int)( ( *yuv++ - 128 ) * 0.707 );
2326  int V2 = 2 * V;
2327  int UV = -U - V;
2328 
2329  // Original equations
2330  // R = Y + 1.402 V
2331  // G = Y - 0.344 U - 0.714 V
2332  // B = Y + 1.772 U
2333  int R = Y + V2;
2334  if ( ( R >> 8 ) > 0 )
2335  R = 255;
2336  else if ( R < 0 )
2337  R = 0;
2338 
2339  int G = Y + UV;
2340  if ( ( G >> 8 ) > 0 )
2341  G = 255;
2342  else if ( G < 0 )
2343  G = 0;
2344 
2345  int B = Y + U5;
2346  if ( ( B >> 8 ) > 0 )
2347  B = 255;
2348  else if ( B < 0 )
2349  B = 0;
2350 
2351  *rgba++ = (unsigned char)R;
2352  *rgba++ = (unsigned char)G;
2353  *rgba++ = (unsigned char)B;
2354  *rgba++ = vpRGBa::alpha_default;
2355  }
2356 }
2357 
2365 void
2366 vpImageConvert::YUV444ToRGB( unsigned char *yuv, unsigned char *rgb, unsigned int size )
2367 {
2368  for ( unsigned int i = 0; i < size; i++ )
2369  {
2370  int U = (int)( ( *yuv++ - 128 ) * 0.354 );
2371  int U5 = 5 * U;
2372  int Y = *yuv++;
2373  int V = (int)( ( *yuv++ - 128 ) * 0.707 );
2374  int V2 = 2 * V;
2375  int UV = -U - V;
2376 
2377  // Original equations
2378  // R = Y + 1.402 V
2379  // G = Y - 0.344 U - 0.714 V
2380  // B = Y + 1.772 U
2381  int R = Y + V2;
2382  if ( ( R >> 8 ) > 0 )
2383  R = 255;
2384  else if ( R < 0 )
2385  R = 0;
2386 
2387  int G = Y + UV;
2388  if ( ( G >> 8 ) > 0 )
2389  G = 255;
2390  else if ( G < 0 )
2391  G = 0;
2392 
2393  int B = Y + U5;
2394  if ( ( B >> 8 ) > 0 )
2395  B = 255;
2396  else if ( B < 0 )
2397  B = 0;
2398 
2399  *rgb++ = (unsigned char)R;
2400  *rgb++ = (unsigned char)G;
2401  *rgb++ = (unsigned char)B;
2402  }
2403 }
2404 
2412 void
2413 vpImageConvert::YUV444ToGrey( unsigned char *yuv, unsigned char *grey, unsigned int size )
2414 {
2415  yuv++;
2416  for ( unsigned int i = 0; i < size; i++ )
2417  {
2418  *grey++ = *yuv;
2419  yuv = yuv + 3;
2420  }
2421 }
2422 
2433 void
2434 vpImageConvert::YV12ToRGBa( unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height )
2435 {
2436  // std::cout << "call optimized ConvertYV12ToRGBa()" << std::endl;
2437  int U, V, R, G, B, V2, U5, UV;
2438  int Y0, Y1, Y2, Y3;
2439  unsigned int size = width * height;
2440  unsigned char *iV = yuv + size;
2441  unsigned char *iU = yuv + 5 * size / 4;
2442  for ( unsigned int i = 0; i < height / 2; i++ )
2443  {
2444  for ( unsigned int j = 0; j < width / 2; j++ )
2445  {
2446  U = (int)( ( *iU++ - 128 ) * 0.354 );
2447  U5 = 5 * U;
2448  V = (int)( ( *iV++ - 128 ) * 0.707 );
2449  V2 = 2 * V;
2450  UV = -U - V;
2451  Y0 = *yuv++;
2452  Y1 = *yuv;
2453  yuv = yuv + width - 1;
2454  Y2 = *yuv++;
2455  Y3 = *yuv;
2456  yuv = yuv - width + 1;
2457 
2458  // Original equations
2459  // R = Y + 1.402 V
2460  // G = Y - 0.344 U - 0.714 V
2461  // B = Y + 1.772 U
2462  R = Y0 + V2;
2463  if ( ( R >> 8 ) > 0 )
2464  R = 255;
2465  else if ( R < 0 )
2466  R = 0;
2467 
2468  G = Y0 + UV;
2469  if ( ( G >> 8 ) > 0 )
2470  G = 255;
2471  else if ( G < 0 )
2472  G = 0;
2473 
2474  B = Y0 + U5;
2475  if ( ( B >> 8 ) > 0 )
2476  B = 255;
2477  else if ( B < 0 )
2478  B = 0;
2479 
2480  *rgba++ = (unsigned char)R;
2481  *rgba++ = (unsigned char)G;
2482  *rgba++ = (unsigned char)B;
2483  *rgba++ = vpRGBa::alpha_default;
2484 
2485  //---
2486  R = Y1 + V2;
2487  if ( ( R >> 8 ) > 0 )
2488  R = 255;
2489  else if ( R < 0 )
2490  R = 0;
2491 
2492  G = Y1 + UV;
2493  if ( ( G >> 8 ) > 0 )
2494  G = 255;
2495  else if ( G < 0 )
2496  G = 0;
2497 
2498  B = Y1 + U5;
2499  if ( ( B >> 8 ) > 0 )
2500  B = 255;
2501  else if ( B < 0 )
2502  B = 0;
2503 
2504  *rgba++ = (unsigned char)R;
2505  *rgba++ = (unsigned char)G;
2506  *rgba++ = (unsigned char)B;
2507  *rgba = 0;
2508  rgba = rgba + 4 * width - 7;
2509 
2510  //---
2511  R = Y2 + V2;
2512  if ( ( R >> 8 ) > 0 )
2513  R = 255;
2514  else if ( R < 0 )
2515  R = 0;
2516 
2517  G = Y2 + UV;
2518  if ( ( G >> 8 ) > 0 )
2519  G = 255;
2520  else if ( G < 0 )
2521  G = 0;
2522 
2523  B = Y2 + U5;
2524  if ( ( B >> 8 ) > 0 )
2525  B = 255;
2526  else if ( B < 0 )
2527  B = 0;
2528 
2529  *rgba++ = (unsigned char)R;
2530  *rgba++ = (unsigned char)G;
2531  *rgba++ = (unsigned char)B;
2532  *rgba++ = vpRGBa::alpha_default;
2533 
2534  //---
2535  R = Y3 + V2;
2536  if ( ( R >> 8 ) > 0 )
2537  R = 255;
2538  else if ( R < 0 )
2539  R = 0;
2540 
2541  G = Y3 + UV;
2542  if ( ( G >> 8 ) > 0 )
2543  G = 255;
2544  else if ( G < 0 )
2545  G = 0;
2546 
2547  B = Y3 + U5;
2548  if ( ( B >> 8 ) > 0 )
2549  B = 255;
2550  else if ( B < 0 )
2551  B = 0;
2552 
2553  *rgba++ = (unsigned char)R;
2554  *rgba++ = (unsigned char)G;
2555  *rgba++ = (unsigned char)B;
2556  *rgba = vpRGBa::alpha_default;
2557  rgba = rgba - 4 * width + 1;
2558  }
2559  yuv += width;
2560  rgba += 4 * width;
2561  }
2562 }
2563 
2572 void
2573 vpImageConvert::YV12ToRGB( unsigned char *yuv, unsigned char *rgb, unsigned int height, unsigned int width )
2574 {
2575  // std::cout << "call optimized ConvertYV12ToRGB()" << std::endl;
2576  int U, V, R, G, B, V2, U5, UV;
2577  int Y0, Y1, Y2, Y3;
2578  unsigned int size = width * height;
2579  unsigned char *iV = yuv + size;
2580  unsigned char *iU = yuv + 5 * size / 4;
2581  for ( unsigned int i = 0; i < height / 2; i++ )
2582  {
2583  for ( unsigned int j = 0; j < width / 2; j++ )
2584  {
2585  U = (int)( ( *iU++ - 128 ) * 0.354 );
2586  U5 = 5 * U;
2587  V = (int)( ( *iV++ - 128 ) * 0.707 );
2588  V2 = 2 * V;
2589  UV = -U - V;
2590  Y0 = *yuv++;
2591  Y1 = *yuv;
2592  yuv = yuv + width - 1;
2593  Y2 = *yuv++;
2594  Y3 = *yuv;
2595  yuv = yuv - width + 1;
2596 
2597  // Original equations
2598  // R = Y + 1.402 V
2599  // G = Y - 0.344 U - 0.714 V
2600  // B = Y + 1.772 U
2601  R = Y0 + V2;
2602  if ( ( R >> 8 ) > 0 )
2603  R = 255;
2604  else if ( R < 0 )
2605  R = 0;
2606 
2607  G = Y0 + UV;
2608  if ( ( G >> 8 ) > 0 )
2609  G = 255;
2610  else if ( G < 0 )
2611  G = 0;
2612 
2613  B = Y0 + U5;
2614  if ( ( B >> 8 ) > 0 )
2615  B = 255;
2616  else if ( B < 0 )
2617  B = 0;
2618 
2619  *rgb++ = (unsigned char)R;
2620  *rgb++ = (unsigned char)G;
2621  *rgb++ = (unsigned char)B;
2622 
2623  //---
2624  R = Y1 + V2;
2625  if ( ( R >> 8 ) > 0 )
2626  R = 255;
2627  else if ( R < 0 )
2628  R = 0;
2629 
2630  G = Y1 + UV;
2631  if ( ( G >> 8 ) > 0 )
2632  G = 255;
2633  else if ( G < 0 )
2634  G = 0;
2635 
2636  B = Y1 + U5;
2637  if ( ( B >> 8 ) > 0 )
2638  B = 255;
2639  else if ( B < 0 )
2640  B = 0;
2641 
2642  *rgb++ = (unsigned char)R;
2643  *rgb++ = (unsigned char)G;
2644  *rgb = (unsigned char)B;
2645  rgb = rgb + 3 * width - 5;
2646 
2647  //---
2648  R = Y2 + V2;
2649  if ( ( R >> 8 ) > 0 )
2650  R = 255;
2651  else if ( R < 0 )
2652  R = 0;
2653 
2654  G = Y2 + UV;
2655  if ( ( G >> 8 ) > 0 )
2656  G = 255;
2657  else if ( G < 0 )
2658  G = 0;
2659 
2660  B = Y2 + U5;
2661  if ( ( B >> 8 ) > 0 )
2662  B = 255;
2663  else if ( B < 0 )
2664  B = 0;
2665 
2666  *rgb++ = (unsigned char)R;
2667  *rgb++ = (unsigned char)G;
2668  *rgb++ = (unsigned char)B;
2669 
2670  //---
2671  R = Y3 + V2;
2672  if ( ( R >> 8 ) > 0 )
2673  R = 255;
2674  else if ( R < 0 )
2675  R = 0;
2676 
2677  G = Y3 + UV;
2678  if ( ( G >> 8 ) > 0 )
2679  G = 255;
2680  else if ( G < 0 )
2681  G = 0;
2682 
2683  B = Y3 + U5;
2684  if ( ( B >> 8 ) > 0 )
2685  B = 255;
2686  else if ( B < 0 )
2687  B = 0;
2688 
2689  *rgb++ = (unsigned char)R;
2690  *rgb++ = (unsigned char)G;
2691  *rgb = (unsigned char)B;
2692  rgb = rgb - 3 * width + 1;
2693  }
2694  yuv += width;
2695  rgb += 3 * width;
2696  }
2697 }
2698 
2709 void
2710 vpImageConvert::YVU9ToRGBa( unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height )
2711 {
2712  // std::cout << "call optimized ConvertYVU9ToRGBa()" << std::endl;
2713  int U, V, R, G, B, V2, U5, UV;
2714  int Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9, Y10, Y11, Y12, Y13, Y14, Y15;
2715  unsigned int size = width * height;
2716  unsigned char *iV = yuv + size;
2717  unsigned char *iU = yuv + 17 * size / 16;
2718  for ( unsigned int i = 0; i < height / 4; i++ )
2719  {
2720  for ( unsigned int j = 0; j < width / 4; j++ )
2721  {
2722  U = (int)( ( *iU++ - 128 ) * 0.354 );
2723  U5 = 5 * U;
2724  V = (int)( ( *iV++ - 128 ) * 0.707 );
2725  V2 = 2 * V;
2726  UV = -U - V;
2727  Y0 = *yuv++;
2728  Y1 = *yuv++;
2729  Y2 = *yuv++;
2730  Y3 = *yuv;
2731  yuv = yuv + width - 3;
2732  Y4 = *yuv++;
2733  Y5 = *yuv++;
2734  Y6 = *yuv++;
2735  Y7 = *yuv;
2736  yuv = yuv + width - 3;
2737  Y8 = *yuv++;
2738  Y9 = *yuv++;
2739  Y10 = *yuv++;
2740  Y11 = *yuv;
2741  yuv = yuv + width - 3;
2742  Y12 = *yuv++;
2743  Y13 = *yuv++;
2744  Y14 = *yuv++;
2745  Y15 = *yuv;
2746  yuv = yuv - 3 * width + 1;
2747 
2748  // Original equations
2749  // R = Y + 1.402 V
2750  // G = Y - 0.344 U - 0.714 V
2751  // B = Y + 1.772 U
2752  R = Y0 + V2;
2753  if ( ( R >> 8 ) > 0 )
2754  R = 255;
2755  else if ( R < 0 )
2756  R = 0;
2757 
2758  G = Y0 + UV;
2759  if ( ( G >> 8 ) > 0 )
2760  G = 255;
2761  else if ( G < 0 )
2762  G = 0;
2763 
2764  B = Y0 + U5;
2765  if ( ( B >> 8 ) > 0 )
2766  B = 255;
2767  else if ( B < 0 )
2768  B = 0;
2769 
2770  *rgba++ = (unsigned char)R;
2771  *rgba++ = (unsigned char)G;
2772  *rgba++ = (unsigned char)B;
2773  *rgba++ = vpRGBa::alpha_default;
2774 
2775  //---
2776  R = Y1 + V2;
2777  if ( ( R >> 8 ) > 0 )
2778  R = 255;
2779  else if ( R < 0 )
2780  R = 0;
2781 
2782  G = Y1 + UV;
2783  if ( ( G >> 8 ) > 0 )
2784  G = 255;
2785  else if ( G < 0 )
2786  G = 0;
2787 
2788  B = Y1 + U5;
2789  if ( ( B >> 8 ) > 0 )
2790  B = 255;
2791  else if ( B < 0 )
2792  B = 0;
2793 
2794  *rgba++ = (unsigned char)R;
2795  *rgba++ = (unsigned char)G;
2796  *rgba++ = (unsigned char)B;
2797  *rgba++ = vpRGBa::alpha_default;
2798 
2799  //---
2800  R = Y2 + V2;
2801  if ( ( R >> 8 ) > 0 )
2802  R = 255;
2803  else if ( R < 0 )
2804  R = 0;
2805 
2806  G = Y2 + UV;
2807  if ( ( G >> 8 ) > 0 )
2808  G = 255;
2809  else if ( G < 0 )
2810  G = 0;
2811 
2812  B = Y2 + U5;
2813  if ( ( B >> 8 ) > 0 )
2814  B = 255;
2815  else if ( B < 0 )
2816  B = 0;
2817 
2818  *rgba++ = (unsigned char)R;
2819  *rgba++ = (unsigned char)G;
2820  *rgba++ = (unsigned char)B;
2821  *rgba++ = vpRGBa::alpha_default;
2822 
2823  //---
2824  R = Y3 + V2;
2825  if ( ( R >> 8 ) > 0 )
2826  R = 255;
2827  else if ( R < 0 )
2828  R = 0;
2829 
2830  G = Y3 + UV;
2831  if ( ( G >> 8 ) > 0 )
2832  G = 255;
2833  else if ( G < 0 )
2834  G = 0;
2835 
2836  B = Y3 + U5;
2837  if ( ( B >> 8 ) > 0 )
2838  B = 255;
2839  else if ( B < 0 )
2840  B = 0;
2841 
2842  *rgba++ = (unsigned char)R;
2843  *rgba++ = (unsigned char)G;
2844  *rgba++ = (unsigned char)B;
2845  *rgba = vpRGBa::alpha_default;
2846  rgba = rgba + 4 * width - 15;
2847 
2848  R = Y4 + V2;
2849  if ( ( R >> 8 ) > 0 )
2850  R = 255;
2851  else if ( R < 0 )
2852  R = 0;
2853 
2854  G = Y4 + UV;
2855  if ( ( G >> 8 ) > 0 )
2856  G = 255;
2857  else if ( G < 0 )
2858  G = 0;
2859 
2860  B = Y4 + U5;
2861  if ( ( B >> 8 ) > 0 )
2862  B = 255;
2863  else if ( B < 0 )
2864  B = 0;
2865 
2866  *rgba++ = (unsigned char)R;
2867  *rgba++ = (unsigned char)G;
2868  *rgba++ = (unsigned char)B;
2869  *rgba++ = vpRGBa::alpha_default;
2870 
2871  //---
2872  R = Y5 + V2;
2873  if ( ( R >> 8 ) > 0 )
2874  R = 255;
2875  else if ( R < 0 )
2876  R = 0;
2877 
2878  G = Y5 + UV;
2879  if ( ( G >> 8 ) > 0 )
2880  G = 255;
2881  else if ( G < 0 )
2882  G = 0;
2883 
2884  B = Y5 + U5;
2885  if ( ( B >> 8 ) > 0 )
2886  B = 255;
2887  else if ( B < 0 )
2888  B = 0;
2889 
2890  *rgba++ = (unsigned char)R;
2891  *rgba++ = (unsigned char)G;
2892  *rgba++ = (unsigned char)B;
2893  *rgba++ = vpRGBa::alpha_default;
2894 
2895  //---
2896  R = Y6 + V2;
2897  if ( ( R >> 8 ) > 0 )
2898  R = 255;
2899  else if ( R < 0 )
2900  R = 0;
2901 
2902  G = Y6 + UV;
2903  if ( ( G >> 8 ) > 0 )
2904  G = 255;
2905  else if ( G < 0 )
2906  G = 0;
2907 
2908  B = Y6 + U5;
2909  if ( ( B >> 8 ) > 0 )
2910  B = 255;
2911  else if ( B < 0 )
2912  B = 0;
2913 
2914  *rgba++ = (unsigned char)R;
2915  *rgba++ = (unsigned char)G;
2916  *rgba++ = (unsigned char)B;
2917  *rgba++ = vpRGBa::alpha_default;
2918 
2919  //---
2920  R = Y7 + V2;
2921  if ( ( R >> 8 ) > 0 )
2922  R = 255;
2923  else if ( R < 0 )
2924  R = 0;
2925 
2926  G = Y7 + UV;
2927  if ( ( G >> 8 ) > 0 )
2928  G = 255;
2929  else if ( G < 0 )
2930  G = 0;
2931 
2932  B = Y7 + U5;
2933  if ( ( B >> 8 ) > 0 )
2934  B = 255;
2935  else if ( B < 0 )
2936  B = 0;
2937 
2938  *rgba++ = (unsigned char)R;
2939  *rgba++ = (unsigned char)G;
2940  *rgba++ = (unsigned char)B;
2941  *rgba = vpRGBa::alpha_default;
2942  rgba = rgba + 4 * width - 15;
2943 
2944  R = Y8 + V2;
2945  if ( ( R >> 8 ) > 0 )
2946  R = 255;
2947  else if ( R < 0 )
2948  R = 0;
2949 
2950  G = Y8 + UV;
2951  if ( ( G >> 8 ) > 0 )
2952  G = 255;
2953  else if ( G < 0 )
2954  G = 0;
2955 
2956  B = Y8 + U5;
2957  if ( ( B >> 8 ) > 0 )
2958  B = 255;
2959  else if ( B < 0 )
2960  B = 0;
2961 
2962  *rgba++ = (unsigned char)R;
2963  *rgba++ = (unsigned char)G;
2964  *rgba++ = (unsigned char)B;
2965  *rgba++ = vpRGBa::alpha_default;
2966 
2967  //---
2968  R = Y9 + V2;
2969  if ( ( R >> 8 ) > 0 )
2970  R = 255;
2971  else if ( R < 0 )
2972  R = 0;
2973 
2974  G = Y9 + UV;
2975  if ( ( G >> 8 ) > 0 )
2976  G = 255;
2977  else if ( G < 0 )
2978  G = 0;
2979 
2980  B = Y9 + U5;
2981  if ( ( B >> 8 ) > 0 )
2982  B = 255;
2983  else if ( B < 0 )
2984  B = 0;
2985 
2986  *rgba++ = (unsigned char)R;
2987  *rgba++ = (unsigned char)G;
2988  *rgba++ = (unsigned char)B;
2989  *rgba++ = vpRGBa::alpha_default;
2990 
2991  //---
2992  R = Y10 + V2;
2993  if ( ( R >> 8 ) > 0 )
2994  R = 255;
2995  else if ( R < 0 )
2996  R = 0;
2997 
2998  G = Y10 + UV;
2999  if ( ( G >> 8 ) > 0 )
3000  G = 255;
3001  else if ( G < 0 )
3002  G = 0;
3003 
3004  B = Y10 + U5;
3005  if ( ( B >> 8 ) > 0 )
3006  B = 255;
3007  else if ( B < 0 )
3008  B = 0;
3009 
3010  *rgba++ = (unsigned char)R;
3011  *rgba++ = (unsigned char)G;
3012  *rgba++ = (unsigned char)B;
3013  *rgba++ = vpRGBa::alpha_default;
3014 
3015  //---
3016  R = Y11 + V2;
3017  if ( ( R >> 8 ) > 0 )
3018  R = 255;
3019  else if ( R < 0 )
3020  R = 0;
3021 
3022  G = Y11 + UV;
3023  if ( ( G >> 8 ) > 0 )
3024  G = 255;
3025  else if ( G < 0 )
3026  G = 0;
3027 
3028  B = Y11 + U5;
3029  if ( ( B >> 8 ) > 0 )
3030  B = 255;
3031  else if ( B < 0 )
3032  B = 0;
3033 
3034  *rgba++ = (unsigned char)R;
3035  *rgba++ = (unsigned char)G;
3036  *rgba++ = (unsigned char)B;
3037  *rgba = vpRGBa::alpha_default;
3038  rgba = rgba + 4 * width - 15;
3039 
3040  R = Y12 + V2;
3041  if ( ( R >> 8 ) > 0 )
3042  R = 255;
3043  else if ( R < 0 )
3044  R = 0;
3045 
3046  G = Y12 + UV;
3047  if ( ( G >> 8 ) > 0 )
3048  G = 255;
3049  else if ( G < 0 )
3050  G = 0;
3051 
3052  B = Y12 + U5;
3053  if ( ( B >> 8 ) > 0 )
3054  B = 255;
3055  else if ( B < 0 )
3056  B = 0;
3057 
3058  *rgba++ = (unsigned char)R;
3059  *rgba++ = (unsigned char)G;
3060  *rgba++ = (unsigned char)B;
3061  *rgba++ = vpRGBa::alpha_default;
3062 
3063  //---
3064  R = Y13 + V2;
3065  if ( ( R >> 8 ) > 0 )
3066  R = 255;
3067  else if ( R < 0 )
3068  R = 0;
3069 
3070  G = Y13 + UV;
3071  if ( ( G >> 8 ) > 0 )
3072  G = 255;
3073  else if ( G < 0 )
3074  G = 0;
3075 
3076  B = Y13 + U5;
3077  if ( ( B >> 8 ) > 0 )
3078  B = 255;
3079  else if ( B < 0 )
3080  B = 0;
3081 
3082  *rgba++ = (unsigned char)R;
3083  *rgba++ = (unsigned char)G;
3084  *rgba++ = (unsigned char)B;
3085  *rgba++ = vpRGBa::alpha_default;
3086 
3087  //---
3088  R = Y14 + V2;
3089  if ( ( R >> 8 ) > 0 )
3090  R = 255;
3091  else if ( R < 0 )
3092  R = 0;
3093 
3094  G = Y14 + UV;
3095  if ( ( G >> 8 ) > 0 )
3096  G = 255;
3097  else if ( G < 0 )
3098  G = 0;
3099 
3100  B = Y14 + U5;
3101  if ( ( B >> 8 ) > 0 )
3102  B = 255;
3103  else if ( B < 0 )
3104  B = 0;
3105 
3106  *rgba++ = (unsigned char)R;
3107  *rgba++ = (unsigned char)G;
3108  *rgba++ = (unsigned char)B;
3109  *rgba++ = vpRGBa::alpha_default;
3110 
3111  //---
3112  R = Y15 + V2;
3113  if ( ( R >> 8 ) > 0 )
3114  R = 255;
3115  else if ( R < 0 )
3116  R = 0;
3117 
3118  G = Y15 + UV;
3119  if ( ( G >> 8 ) > 0 )
3120  G = 255;
3121  else if ( G < 0 )
3122  G = 0;
3123 
3124  B = Y15 + U5;
3125  if ( ( B >> 8 ) > 0 )
3126  B = 255;
3127  else if ( B < 0 )
3128  B = 0;
3129 
3130  *rgba++ = (unsigned char)R;
3131  *rgba++ = (unsigned char)G;
3132  *rgba++ = (unsigned char)B;
3133  *rgba = vpRGBa::alpha_default;
3134  rgba = rgba - 12 * width + 1;
3135  }
3136  yuv += 3 * width;
3137  rgba += 12 * width;
3138  }
3139 }
3140 
3148 void
3149 vpImageConvert::YVU9ToRGB( unsigned char *yuv, unsigned char *rgb, unsigned int height, unsigned int width )
3150 {
3151  // std::cout << "call optimized ConvertYVU9ToRGB()" << std::endl;
3152  int U, V, R, G, B, V2, U5, UV;
3153  int Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9, Y10, Y11, Y12, Y13, Y14, Y15;
3154  unsigned int size = width * height;
3155  unsigned char *iV = yuv + size;
3156  unsigned char *iU = yuv + 17 * size / 16;
3157  for ( unsigned int i = 0; i < height / 4; i++ )
3158  {
3159  for ( unsigned int j = 0; j < width / 4; j++ )
3160  {
3161  U = (int)( ( *iU++ - 128 ) * 0.354 );
3162  U5 = 5 * U;
3163  V = (int)( ( *iV++ - 128 ) * 0.707 );
3164  V2 = 2 * V;
3165  UV = -U - V;
3166  Y0 = *yuv++;
3167  Y1 = *yuv++;
3168  Y2 = *yuv++;
3169  Y3 = *yuv;
3170  yuv = yuv + width - 3;
3171  Y4 = *yuv++;
3172  Y5 = *yuv++;
3173  Y6 = *yuv++;
3174  Y7 = *yuv;
3175  yuv = yuv + width - 3;
3176  Y8 = *yuv++;
3177  Y9 = *yuv++;
3178  Y10 = *yuv++;
3179  Y11 = *yuv;
3180  yuv = yuv + width - 3;
3181  Y12 = *yuv++;
3182  Y13 = *yuv++;
3183  Y14 = *yuv++;
3184  Y15 = *yuv;
3185  yuv = yuv - 3 * width + 1;
3186 
3187  // Original equations
3188  // R = Y + 1.402 V
3189  // G = Y - 0.344 U - 0.714 V
3190  // B = Y + 1.772 U
3191  R = Y0 + V2;
3192  if ( ( R >> 8 ) > 0 )
3193  R = 255;
3194  else if ( R < 0 )
3195  R = 0;
3196 
3197  G = Y0 + UV;
3198  if ( ( G >> 8 ) > 0 )
3199  G = 255;
3200  else if ( G < 0 )
3201  G = 0;
3202 
3203  B = Y0 + U5;
3204  if ( ( B >> 8 ) > 0 )
3205  B = 255;
3206  else if ( B < 0 )
3207  B = 0;
3208 
3209  *rgb++ = (unsigned char)R;
3210  *rgb++ = (unsigned char)G;
3211  *rgb++ = (unsigned char)B;
3212 
3213  //---
3214  R = Y1 + V2;
3215  if ( ( R >> 8 ) > 0 )
3216  R = 255;
3217  else if ( R < 0 )
3218  R = 0;
3219 
3220  G = Y1 + UV;
3221  if ( ( G >> 8 ) > 0 )
3222  G = 255;
3223  else if ( G < 0 )
3224  G = 0;
3225 
3226  B = Y1 + U5;
3227  if ( ( B >> 8 ) > 0 )
3228  B = 255;
3229  else if ( B < 0 )
3230  B = 0;
3231 
3232  *rgb++ = (unsigned char)R;
3233  *rgb++ = (unsigned char)G;
3234  *rgb++ = (unsigned char)B;
3235 
3236  //---
3237  R = Y2 + V2;
3238  if ( ( R >> 8 ) > 0 )
3239  R = 255;
3240  else if ( R < 0 )
3241  R = 0;
3242 
3243  G = Y2 + UV;
3244  if ( ( G >> 8 ) > 0 )
3245  G = 255;
3246  else if ( G < 0 )
3247  G = 0;
3248 
3249  B = Y2 + U5;
3250  if ( ( B >> 8 ) > 0 )
3251  B = 255;
3252  else if ( B < 0 )
3253  B = 0;
3254 
3255  *rgb++ = (unsigned char)R;
3256  *rgb++ = (unsigned char)G;
3257  *rgb++ = (unsigned char)B;
3258 
3259  //---
3260  R = Y3 + V2;
3261  if ( ( R >> 8 ) > 0 )
3262  R = 255;
3263  else if ( R < 0 )
3264  R = 0;
3265 
3266  G = Y3 + UV;
3267  if ( ( G >> 8 ) > 0 )
3268  G = 255;
3269  else if ( G < 0 )
3270  G = 0;
3271 
3272  B = Y3 + U5;
3273  if ( ( B >> 8 ) > 0 )
3274  B = 255;
3275  else if ( B < 0 )
3276  B = 0;
3277 
3278  *rgb++ = (unsigned char)R;
3279  *rgb++ = (unsigned char)G;
3280  *rgb = (unsigned char)B;
3281  rgb = rgb + 3 * width - 11;
3282 
3283  R = Y4 + V2;
3284  if ( ( R >> 8 ) > 0 )
3285  R = 255;
3286  else if ( R < 0 )
3287  R = 0;
3288 
3289  G = Y4 + UV;
3290  if ( ( G >> 8 ) > 0 )
3291  G = 255;
3292  else if ( G < 0 )
3293  G = 0;
3294 
3295  B = Y4 + U5;
3296  if ( ( B >> 8 ) > 0 )
3297  B = 255;
3298  else if ( B < 0 )
3299  B = 0;
3300 
3301  *rgb++ = (unsigned char)R;
3302  *rgb++ = (unsigned char)G;
3303  *rgb++ = (unsigned char)B;
3304 
3305  //---
3306  R = Y5 + V2;
3307  if ( ( R >> 8 ) > 0 )
3308  R = 255;
3309  else if ( R < 0 )
3310  R = 0;
3311 
3312  G = Y5 + UV;
3313  if ( ( G >> 8 ) > 0 )
3314  G = 255;
3315  else if ( G < 0 )
3316  G = 0;
3317 
3318  B = Y5 + U5;
3319  if ( ( B >> 8 ) > 0 )
3320  B = 255;
3321  else if ( B < 0 )
3322  B = 0;
3323 
3324  *rgb++ = (unsigned char)R;
3325  *rgb++ = (unsigned char)G;
3326  *rgb++ = (unsigned char)B;
3327 
3328  //---
3329  R = Y6 + V2;
3330  if ( ( R >> 8 ) > 0 )
3331  R = 255;
3332  else if ( R < 0 )
3333  R = 0;
3334 
3335  G = Y6 + UV;
3336  if ( ( G >> 8 ) > 0 )
3337  G = 255;
3338  else if ( G < 0 )
3339  G = 0;
3340 
3341  B = Y6 + U5;
3342  if ( ( B >> 8 ) > 0 )
3343  B = 255;
3344  else if ( B < 0 )
3345  B = 0;
3346 
3347  *rgb++ = (unsigned char)R;
3348  *rgb++ = (unsigned char)G;
3349  *rgb++ = (unsigned char)B;
3350 
3351  //---
3352  R = Y7 + V2;
3353  if ( ( R >> 8 ) > 0 )
3354  R = 255;
3355  else if ( R < 0 )
3356  R = 0;
3357 
3358  G = Y7 + UV;
3359  if ( ( G >> 8 ) > 0 )
3360  G = 255;
3361  else if ( G < 0 )
3362  G = 0;
3363 
3364  B = Y7 + U5;
3365  if ( ( B >> 8 ) > 0 )
3366  B = 255;
3367  else if ( B < 0 )
3368  B = 0;
3369 
3370  *rgb++ = (unsigned char)R;
3371  *rgb++ = (unsigned char)G;
3372  *rgb = (unsigned char)B;
3373  rgb = rgb + 3 * width - 11;
3374 
3375  R = Y8 + V2;
3376  if ( ( R >> 8 ) > 0 )
3377  R = 255;
3378  else if ( R < 0 )
3379  R = 0;
3380 
3381  G = Y8 + UV;
3382  if ( ( G >> 8 ) > 0 )
3383  G = 255;
3384  else if ( G < 0 )
3385  G = 0;
3386 
3387  B = Y8 + U5;
3388  if ( ( B >> 8 ) > 0 )
3389  B = 255;
3390  else if ( B < 0 )
3391  B = 0;
3392 
3393  *rgb++ = (unsigned char)R;
3394  *rgb++ = (unsigned char)G;
3395  *rgb++ = (unsigned char)B;
3396 
3397  //---
3398  R = Y9 + V2;
3399  if ( ( R >> 8 ) > 0 )
3400  R = 255;
3401  else if ( R < 0 )
3402  R = 0;
3403 
3404  G = Y9 + UV;
3405  if ( ( G >> 8 ) > 0 )
3406  G = 255;
3407  else if ( G < 0 )
3408  G = 0;
3409 
3410  B = Y9 + U5;
3411  if ( ( B >> 8 ) > 0 )
3412  B = 255;
3413  else if ( B < 0 )
3414  B = 0;
3415 
3416  *rgb++ = (unsigned char)R;
3417  *rgb++ = (unsigned char)G;
3418  *rgb++ = (unsigned char)B;
3419 
3420  //---
3421  R = Y10 + V2;
3422  if ( ( R >> 8 ) > 0 )
3423  R = 255;
3424  else if ( R < 0 )
3425  R = 0;
3426 
3427  G = Y10 + UV;
3428  if ( ( G >> 8 ) > 0 )
3429  G = 255;
3430  else if ( G < 0 )
3431  G = 0;
3432 
3433  B = Y10 + U5;
3434  if ( ( B >> 8 ) > 0 )
3435  B = 255;
3436  else if ( B < 0 )
3437  B = 0;
3438 
3439  *rgb++ = (unsigned char)R;
3440  *rgb++ = (unsigned char)G;
3441  *rgb++ = (unsigned char)B;
3442 
3443  //---
3444  R = Y11 + V2;
3445  if ( ( R >> 8 ) > 0 )
3446  R = 255;
3447  else if ( R < 0 )
3448  R = 0;
3449 
3450  G = Y11 + UV;
3451  if ( ( G >> 8 ) > 0 )
3452  G = 255;
3453  else if ( G < 0 )
3454  G = 0;
3455 
3456  B = Y11 + U5;
3457  if ( ( B >> 8 ) > 0 )
3458  B = 255;
3459  else if ( B < 0 )
3460  B = 0;
3461 
3462  *rgb++ = (unsigned char)R;
3463  *rgb++ = (unsigned char)G;
3464  *rgb = (unsigned char)B;
3465  rgb = rgb + 3 * width - 11;
3466 
3467  R = Y12 + V2;
3468  if ( ( R >> 8 ) > 0 )
3469  R = 255;
3470  else if ( R < 0 )
3471  R = 0;
3472 
3473  G = Y12 + UV;
3474  if ( ( G >> 8 ) > 0 )
3475  G = 255;
3476  else if ( G < 0 )
3477  G = 0;
3478 
3479  B = Y12 + U5;
3480  if ( ( B >> 8 ) > 0 )
3481  B = 255;
3482  else if ( B < 0 )
3483  B = 0;
3484 
3485  *rgb++ = (unsigned char)R;
3486  *rgb++ = (unsigned char)G;
3487  *rgb++ = (unsigned char)B;
3488 
3489  //---
3490  R = Y13 + V2;
3491  if ( ( R >> 8 ) > 0 )
3492  R = 255;
3493  else if ( R < 0 )
3494  R = 0;
3495 
3496  G = Y13 + UV;
3497  if ( ( G >> 8 ) > 0 )
3498  G = 255;
3499  else if ( G < 0 )
3500  G = 0;
3501 
3502  B = Y13 + U5;
3503  if ( ( B >> 8 ) > 0 )
3504  B = 255;
3505  else if ( B < 0 )
3506  B = 0;
3507 
3508  *rgb++ = (unsigned char)R;
3509  *rgb++ = (unsigned char)G;
3510  *rgb++ = (unsigned char)B;
3511 
3512  //---
3513  R = Y14 + V2;
3514  if ( ( R >> 8 ) > 0 )
3515  R = 255;
3516  else if ( R < 0 )
3517  R = 0;
3518 
3519  G = Y14 + UV;
3520  if ( ( G >> 8 ) > 0 )
3521  G = 255;
3522  else if ( G < 0 )
3523  G = 0;
3524 
3525  B = Y14 + U5;
3526  if ( ( B >> 8 ) > 0 )
3527  B = 255;
3528  else if ( B < 0 )
3529  B = 0;
3530 
3531  *rgb++ = (unsigned char)R;
3532  *rgb++ = (unsigned char)G;
3533  *rgb++ = (unsigned char)B;
3534 
3535  //---
3536  R = Y15 + V2;
3537  if ( ( R >> 8 ) > 0 )
3538  R = 255;
3539  else if ( R < 0 )
3540  R = 0;
3541 
3542  G = Y15 + UV;
3543  if ( ( G >> 8 ) > 0 )
3544  G = 255;
3545  else if ( G < 0 )
3546  G = 0;
3547 
3548  B = Y15 + U5;
3549  if ( ( B >> 8 ) > 0 )
3550  B = 255;
3551  else if ( B < 0 )
3552  B = 0;
3553 
3554  *rgb++ = (unsigned char)R;
3555  *rgb++ = (unsigned char)G;
3556  *rgb++ = (unsigned char)B;
3557  rgb = rgb - 9 * width + 1;
3558  }
3559  yuv += 3 * width;
3560  rgb += 9 * width;
3561  }
3562 }
3563 
3573 void
3574 vpImageConvert::RGBToRGBa( unsigned char *rgb, unsigned char *rgba, unsigned int size )
3575 {
3576  RGBToRGBa( rgb, rgba, size, 1, false );
3577 }
3578 
3594 void
3595 vpImageConvert::RGBToRGBa( unsigned char *rgb, unsigned char *rgba, unsigned int width, unsigned int height, bool flip )
3596 {
3597  if ( !flip )
3598  {
3599  SimdBgrToBgra( rgb, width, height, width * 3, rgba, width * 4, vpRGBa::alpha_default );
3600  }
3601  else
3602  {
3603  // if we have to flip the image, we start from the end last scanline so the
3604  // step is negative
3605  int lineStep = ( flip ) ? -(int)( width * 3 ) : (int)( width * 3 );
3606 
3607  // starting source address = last line if we need to flip the image
3608  unsigned char *src = ( flip ) ? ( rgb + ( width * height * 3 ) + lineStep ) : rgb;
3609 
3610  unsigned int j = 0;
3611  unsigned int i = 0;
3612 
3613  for ( i = 0; i < height; i++ )
3614  {
3615  unsigned char *line = src;
3616  for ( j = 0; j < width; j++ )
3617  {
3618  *rgba++ = *( line++ );
3619  *rgba++ = *( line++ );
3620  *rgba++ = *( line++ );
3621  *rgba++ = vpRGBa::alpha_default;
3622  }
3623  // go to the next line
3624  src += lineStep;
3625  }
3626  }
3627 }
3628 
3641 void
3642 vpImageConvert::RGBaToRGB( unsigned char *rgba, unsigned char *rgb, unsigned int size )
3643 {
3644  SimdBgraToBgr( rgba, size, 1, size * 4, rgb, size * 3 );
3645 }
3646 
3659 void
3660 vpImageConvert::RGBToGrey( unsigned char *rgb, unsigned char *grey, unsigned int size )
3661 {
3662  RGBToGrey( rgb, grey, size, 1, false );
3663 }
3664 
3678 void
3679 vpImageConvert::RGBToGrey( unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height, bool flip )
3680 {
3681  if ( !flip )
3682  {
3683  SimdRgbToGray( rgb, width, height, width * 3, grey, width );
3684  }
3685  else
3686  {
3687  // if we have to flip the image, we start from the end last scanline so
3688  // the step is negative
3689  int lineStep = ( flip ) ? -(int)( width * 3 ) : (int)( width * 3 );
3690 
3691  // starting source address = last line if we need to flip the image
3692  unsigned char *src = ( flip ) ? rgb + ( width * height * 3 ) + lineStep : rgb;
3693 
3694  unsigned int j = 0;
3695  unsigned int i = 0;
3696 
3697  unsigned r, g, b;
3698 
3699  for ( i = 0; i < height; i++ )
3700  {
3701  unsigned char *line = src;
3702  for ( j = 0; j < width; j++ )
3703  {
3704  r = *( line++ );
3705  g = *( line++ );
3706  b = *( line++ );
3707  *grey++ = (unsigned char)( 0.2126 * r + 0.7152 * g + 0.0722 * b );
3708  }
3709 
3710  // go to the next line
3711  src += lineStep;
3712  }
3713  }
3714 }
3715 
3731 void
3732 vpImageConvert::RGBaToGrey( unsigned char *rgba, unsigned char *grey, unsigned int width, unsigned int height,
3733  unsigned int
3734 #if defined _OPENMP
3735  nThreads
3736 #endif
3737 )
3738 {
3739 #if defined _OPENMP
3740  if ( nThreads > 0 )
3741  {
3742  omp_set_num_threads( static_cast< int >( nThreads ) );
3743  }
3744 #pragma omp parallel for
3745 #endif
3746  for ( int i = 0; i < static_cast< int >( height ); i++ )
3747  {
3748  SimdRgbaToGray( rgba + i * width * 4, width, 1, width * 4, grey + i * width, width );
3749  }
3750 }
3751 
3766 void
3767 vpImageConvert::RGBaToGrey( unsigned char *rgba, unsigned char *grey, unsigned int size )
3768 {
3769  SimdRgbaToGray( rgba, size, 1, size * 4, grey, size );
3770 }
3771 
3783 void
3784 vpImageConvert::GreyToRGBa( unsigned char *grey, unsigned char *rgba, unsigned int width, unsigned int height )
3785 {
3786  SimdGrayToBgra( grey, width, height, width, rgba, width * sizeof( vpRGBa ), vpRGBa::alpha_default );
3787 }
3788 
3801 void
3802 vpImageConvert::GreyToRGBa( unsigned char *grey, unsigned char *rgba, unsigned int size )
3803 {
3804  GreyToRGBa( grey, rgba, size, 1 );
3805 }
3806 
3817 void
3818 vpImageConvert::GreyToRGB( unsigned char *grey, unsigned char *rgb, unsigned int size )
3819 {
3820  SimdGrayToBgr( grey, size, 1, size, rgb, size * 3 );
3821 }
3822 
3838 void
3839 vpImageConvert::BGRToRGBa( unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height, bool flip )
3840 {
3841  if ( !flip )
3842  {
3843  SimdRgbToBgra( bgr, width, height, width * 3, rgba, width * sizeof( vpRGBa ), vpRGBa::alpha_default );
3844  }
3845  else
3846  {
3847  // if we have to flip the image, we start from the end last scanline so the
3848  // step is negative
3849  int lineStep = ( flip ) ? -(int)( width * 3 ) : (int)( width * 3 );
3850 
3851  // starting source address = last line if we need to flip the image
3852  unsigned char *src = ( flip ) ? ( bgr + ( width * height * 3 ) + lineStep ) : bgr;
3853 
3854  for ( unsigned int i = 0; i < height; i++ )
3855  {
3856  unsigned char *line = src;
3857  for ( unsigned int j = 0; j < width; j++ )
3858  {
3859  *rgba++ = *( line + 2 );
3860  *rgba++ = *( line + 1 );
3861  *rgba++ = *( line + 0 );
3862  *rgba++ = vpRGBa::alpha_default;
3863 
3864  line += 3;
3865  }
3866  // go to the next line
3867  src += lineStep;
3868  }
3869  }
3870 }
3871 
3886 void
3887 vpImageConvert::BGRaToRGBa( unsigned char *bgra, unsigned char *rgba, unsigned int width, unsigned int height,
3888  bool flip )
3889 {
3890  if ( !flip )
3891  {
3892  SimdBgraToRgba( bgra, width, height, width * 4, rgba, width * 4 );
3893  }
3894  else
3895  {
3896  // if we have to flip the image, we start from the end last scanline so the
3897  // step is negative
3898  int lineStep = ( flip ) ? -(int)( width * 4 ) : (int)( width * 4 );
3899 
3900  // starting source address = last line if we need to flip the image
3901  unsigned char *src = ( flip ) ? ( bgra + ( width * height * 4 ) + lineStep ) : bgra;
3902 
3903  for ( unsigned int i = 0; i < height; i++ )
3904  {
3905  unsigned char *line = src;
3906  for ( unsigned int j = 0; j < width; j++ )
3907  {
3908  *rgba++ = *( line + 2 );
3909  *rgba++ = *( line + 1 );
3910  *rgba++ = *( line + 0 );
3911  *rgba++ = *( line + 3 );
3912 
3913  line += 4;
3914  }
3915  // go to the next line
3916  src += lineStep;
3917  }
3918  }
3919 }
3920 
3935 void
3936 vpImageConvert::BGRToGrey( unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip,
3937  unsigned int
3938 #if defined _OPENMP
3939  nThreads
3940 #endif
3941 )
3942 {
3943  if ( !flip )
3944  {
3945 #if defined _OPENMP
3946  if ( nThreads > 0 )
3947  {
3948  omp_set_num_threads( static_cast< int >( nThreads ) );
3949  }
3950 #pragma omp parallel for
3951 #endif
3952  for ( int i = 0; i < static_cast< int >( height ); i++ )
3953  {
3954  SimdBgrToGray( bgr + i * width * 3, width, 1, width * 3, grey + i * width, width );
3955  }
3956  }
3957  else
3958  {
3959  // if we have to flip the image, we start from the end last scanline so
3960  // the step is negative
3961  int lineStep = ( flip ) ? -(int)( width * 3 ) : (int)( width * 3 );
3962 
3963  // starting source address = last line if we need to flip the image
3964  unsigned char *src = ( flip ) ? bgr + ( width * height * 3 ) + lineStep : bgr;
3965 
3966  for ( unsigned int i = 0; i < height; i++ )
3967  {
3968  unsigned char *line = src;
3969  for ( unsigned int j = 0; j < width; j++ )
3970  {
3971  *grey++ = (unsigned char)( 0.2126 * *( line + 2 ) + 0.7152 * *( line + 1 ) + 0.0722 * *( line + 0 ) );
3972  line += 3;
3973  }
3974 
3975  // go to the next line
3976  src += lineStep;
3977  }
3978  }
3979 }
3980 
3995 void
3996 vpImageConvert::BGRaToGrey( unsigned char *bgra, unsigned char *grey, unsigned int width, unsigned int height,
3997  bool flip,
3998  unsigned int
3999 #if defined _OPENMP
4000  nThreads
4001 #endif
4002 )
4003 {
4004  if ( !flip )
4005  {
4006 #if defined _OPENMP
4007  if ( nThreads > 0 )
4008  {
4009  omp_set_num_threads( static_cast< int >( nThreads ) );
4010  }
4011 #pragma omp parallel for
4012 #endif
4013  for ( int i = 0; i < static_cast< int >( height ); i++ )
4014  {
4015  SimdBgraToGray( bgra + i * width * 4, width, 1, width * 4, grey + i * width, width );
4016  }
4017  }
4018  else
4019  {
4020  // if we have to flip the image, we start from the end last scanline so
4021  // the step is negative
4022  int lineStep = ( flip ) ? -(int)( width * 4 ) : (int)( width * 4 );
4023 
4024  // starting source address = last line if we need to flip the image
4025  unsigned char *src = ( flip ) ? bgra + ( width * height * 4 ) + lineStep : bgra;
4026 
4027  for ( unsigned int i = 0; i < height; i++ )
4028  {
4029  unsigned char *line = src;
4030  for ( unsigned int j = 0; j < width; j++ )
4031  {
4032  *grey++ = (unsigned char)( 0.2126 * *( line + 2 ) + 0.7152 * *( line + 1 ) + 0.0722 * *( line + 0 ) );
4033  line += 4;
4034  }
4035 
4036  // go to the next line
4037  src += lineStep;
4038  }
4039  }
4040 }
4041 
4045 void
4046 vpImageConvert::computeYCbCrLUT()
4047 {
4048  if ( YCbCrLUTcomputed == false )
4049  {
4050  int index = 256;
4051 
4052  while ( index-- )
4053  {
4054 
4055  int aux = index - 128;
4056  vpImageConvert::vpCrr[index] = (int)( 364.6610 * aux ) >> 8;
4057  vpImageConvert::vpCgb[index] = (int)( -89.8779 * aux ) >> 8;
4058  vpImageConvert::vpCgr[index] = (int)( -185.8154 * aux ) >> 8;
4059  vpImageConvert::vpCbb[index] = (int)( 460.5724 * aux ) >> 8;
4060  }
4061 
4062  YCbCrLUTcomputed = true;
4063  }
4064 }
4065 
4087 void
4088 vpImageConvert::YCbCrToRGB( unsigned char *ycbcr, unsigned char *rgb, unsigned int size )
4089 {
4090  unsigned char *cbv;
4091  unsigned char *crv;
4092  unsigned char *pt_ycbcr = ycbcr;
4093  unsigned char *pt_rgb = rgb;
4094  cbv = pt_ycbcr + 1;
4095  crv = pt_ycbcr + 3;
4096 
4097  vpImageConvert::computeYCbCrLUT();
4098 
4099  int col = 0;
4100 
4101  while ( size-- )
4102  {
4103  int val_r, val_g, val_b;
4104  if ( !( col++ % 2 ) )
4105  {
4106  cbv = pt_ycbcr + 1;
4107  crv = pt_ycbcr + 3;
4108  }
4109 
4110  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4111  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4112  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4113 
4114  vpDEBUG_TRACE( 5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b );
4115 
4116  *pt_rgb++ = ( val_r < 0 ) ? 0u : ( ( val_r > 255 ) ? 255u : (unsigned char)val_r ); // Red component.
4117  *pt_rgb++ = ( val_g < 0 ) ? 0u : ( ( val_g > 255 ) ? 255u : (unsigned char)val_g ); // Green component.
4118  *pt_rgb++ = ( val_b < 0 ) ? 0u : ( ( val_b > 255 ) ? 255u : (unsigned char)val_b ); // Blue component.
4119 
4120  pt_ycbcr += 2;
4121  }
4122 }
4123 
4149 void
4150 vpImageConvert::YCbCrToRGBa( unsigned char *ycbcr, unsigned char *rgba, unsigned int size )
4151 {
4152  unsigned char *cbv;
4153  unsigned char *crv;
4154  unsigned char *pt_ycbcr = ycbcr;
4155  unsigned char *pt_rgba = rgba;
4156  cbv = pt_ycbcr + 1;
4157  crv = pt_ycbcr + 3;
4158 
4159  vpImageConvert::computeYCbCrLUT();
4160 
4161  int col = 0;
4162 
4163  while ( size-- )
4164  {
4165  int val_r, val_g, val_b;
4166  if ( !( col++ % 2 ) )
4167  {
4168  cbv = pt_ycbcr + 1;
4169  crv = pt_ycbcr + 3;
4170  }
4171 
4172  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4173  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4174  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4175 
4176  vpDEBUG_TRACE( 5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b );
4177 
4178  *pt_rgba++ = ( val_r < 0 ) ? 0u : ( ( val_r > 255 ) ? 255u : (unsigned char)val_r ); // Red component.
4179  *pt_rgba++ = ( val_g < 0 ) ? 0u : ( ( val_g > 255 ) ? 255u : (unsigned char)val_g ); // Green component.
4180  *pt_rgba++ = ( val_b < 0 ) ? 0u : ( ( val_b > 255 ) ? 255u : (unsigned char)val_b ); // Blue component.
4181  *pt_rgba++ = vpRGBa::alpha_default;
4182 
4183  pt_ycbcr += 2;
4184  }
4185 }
4186 
4206 void
4207 vpImageConvert::YCbCrToGrey( unsigned char *ycbcr, unsigned char *grey, unsigned int size )
4208 {
4209  unsigned int i = 0, j = 0;
4210 
4211  while ( j < size * 2 )
4212  {
4213  grey[i++] = ycbcr[j];
4214  grey[i++] = ycbcr[j + 2];
4215  j += 4;
4216  }
4217 }
4218 
4240 void
4241 vpImageConvert::YCrCbToRGB( unsigned char *ycrcb, unsigned char *rgb, unsigned int size )
4242 {
4243  unsigned char *cbv;
4244  unsigned char *crv;
4245  unsigned char *pt_ycbcr = ycrcb;
4246  unsigned char *pt_rgb = rgb;
4247  crv = pt_ycbcr + 1;
4248  cbv = pt_ycbcr + 3;
4249 
4250  vpImageConvert::computeYCbCrLUT();
4251 
4252  int col = 0;
4253 
4254  while ( size-- )
4255  {
4256  int val_r, val_g, val_b;
4257  if ( !( col++ % 2 ) )
4258  {
4259  crv = pt_ycbcr + 1;
4260  cbv = pt_ycbcr + 3;
4261  }
4262 
4263  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4264  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4265  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4266 
4267  vpDEBUG_TRACE( 5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b );
4268 
4269  *pt_rgb++ = ( val_r < 0 ) ? 0u : ( ( val_r > 255 ) ? 255u : (unsigned char)val_r ); // Red component.
4270  *pt_rgb++ = ( val_g < 0 ) ? 0u : ( ( val_g > 255 ) ? 255u : (unsigned char)val_g ); // Green component.
4271  *pt_rgb++ = ( val_b < 0 ) ? 0u : ( ( val_b > 255 ) ? 255u : (unsigned char)val_b ); // Blue component.
4272 
4273  pt_ycbcr += 2;
4274  }
4275 }
4276 
4301 void
4302 vpImageConvert::YCrCbToRGBa( unsigned char *ycrcb, unsigned char *rgba, unsigned int size )
4303 {
4304  unsigned char *cbv;
4305  unsigned char *crv;
4306  unsigned char *pt_ycbcr = ycrcb;
4307  unsigned char *pt_rgba = rgba;
4308  crv = pt_ycbcr + 1;
4309  cbv = pt_ycbcr + 3;
4310 
4311  vpImageConvert::computeYCbCrLUT();
4312 
4313  int col = 0;
4314 
4315  while ( size-- )
4316  {
4317  int val_r, val_g, val_b;
4318  if ( !( col++ % 2 ) )
4319  {
4320  crv = pt_ycbcr + 1;
4321  cbv = pt_ycbcr + 3;
4322  }
4323 
4324  val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
4325  val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
4326  val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
4327 
4328  vpDEBUG_TRACE( 5, "[%d] R: %d G: %d B: %d\n", size, val_r, val_g, val_b );
4329 
4330  *pt_rgba++ = ( val_r < 0 ) ? 0u : ( ( val_r > 255 ) ? 255u : (unsigned char)val_r ); // Red component.
4331  *pt_rgba++ = ( val_g < 0 ) ? 0u : ( ( val_g > 255 ) ? 255u : (unsigned char)val_g ); // Green component.
4332  *pt_rgba++ = ( val_b < 0 ) ? 0u : ( ( val_b > 255 ) ? 255u : (unsigned char)val_b ); // Blue component.
4333  *pt_rgba++ = vpRGBa::alpha_default;
4334 
4335  pt_ycbcr += 2;
4336  }
4337 }
4338 
4377 void
4380 {
4381  if ( src.getSize() > 0 )
4382  {
4383  if ( pR )
4384  {
4385  pR->resize( src.getHeight(), src.getWidth() );
4386  }
4387  if ( pG )
4388  {
4389  pG->resize( src.getHeight(), src.getWidth() );
4390  }
4391  if ( pB )
4392  {
4393  pB->resize( src.getHeight(), src.getWidth() );
4394  }
4395  if ( pa )
4396  {
4397  pa->resize( src.getHeight(), src.getWidth() );
4398  }
4399 
4400  unsigned char *ptrR = pR ? pR->bitmap : new unsigned char[src.getSize()];
4401  unsigned char *ptrG = pG ? pG->bitmap : new unsigned char[src.getSize()];
4402  unsigned char *ptrB = pB ? pB->bitmap : new unsigned char[src.getSize()];
4403  unsigned char *ptrA = pa ? pa->bitmap : new unsigned char[src.getSize()];
4404 
4405  SimdDeinterleaveBgra( reinterpret_cast< unsigned char * >( src.bitmap ), src.getWidth() * sizeof( vpRGBa ),
4406  src.getWidth(), src.getHeight(), ptrR, src.getWidth(), ptrG, src.getWidth(), ptrB,
4407  src.getWidth(), ptrA, src.getWidth() );
4408 
4409  if ( !pR )
4410  {
4411  delete[] ptrR;
4412  }
4413  if ( !pG )
4414  {
4415  delete[] ptrG;
4416  }
4417  if ( !pB )
4418  {
4419  delete[] ptrB;
4420  }
4421  if ( !pa )
4422  {
4423  delete[] ptrA;
4424  }
4425  }
4426 }
4427 
4438 void
4441 {
4442  // Check if the input channels have all the same dimensions
4443  std::map< unsigned int, unsigned int > mapOfWidths, mapOfHeights;
4444  if ( R != NULL )
4445  {
4446  mapOfWidths[R->getWidth()]++;
4447  mapOfHeights[R->getHeight()]++;
4448  }
4449 
4450  if ( G != NULL )
4451  {
4452  mapOfWidths[G->getWidth()]++;
4453  mapOfHeights[G->getHeight()]++;
4454  }
4455 
4456  if ( B != NULL )
4457  {
4458  mapOfWidths[B->getWidth()]++;
4459  mapOfHeights[B->getHeight()]++;
4460  }
4461 
4462  if ( a != NULL )
4463  {
4464  mapOfWidths[a->getWidth()]++;
4465  mapOfHeights[a->getHeight()]++;
4466  }
4467 
4468  if ( mapOfWidths.size() == 1 && mapOfHeights.size() == 1 )
4469  {
4470  unsigned int width = mapOfWidths.begin()->first;
4471  unsigned int height = mapOfHeights.begin()->first;
4472 
4473  RGBa.resize( height, width );
4474 
4475  if ( R != NULL && G != NULL && B != NULL && a != NULL )
4476  {
4477  SimdInterleaveBgra( R->bitmap, width, G->bitmap, width, B->bitmap, width, a->bitmap, width, width, height,
4478  reinterpret_cast< uint8_t * >( RGBa.bitmap ), width * sizeof( vpRGBa ) );
4479  }
4480  else
4481  {
4482  unsigned int size = width * height;
4483  for ( unsigned int i = 0; i < size; i++ )
4484  {
4485  if ( R != NULL )
4486  {
4487  RGBa.bitmap[i].R = R->bitmap[i];
4488  }
4489 
4490  if ( G != NULL )
4491  {
4492  RGBa.bitmap[i].G = G->bitmap[i];
4493  }
4494 
4495  if ( B != NULL )
4496  {
4497  RGBa.bitmap[i].B = B->bitmap[i];
4498  }
4499 
4500  if ( a != NULL )
4501  {
4502  RGBa.bitmap[i].A = a->bitmap[i];
4503  }
4504  }
4505  }
4506  }
4507  else
4508  {
4509  throw vpException( vpException::dimensionError, "Mismatched dimensions!" );
4510  }
4511 }
4512 
4523 void
4524 vpImageConvert::MONO16ToGrey( unsigned char *grey16, unsigned char *grey, unsigned int size )
4525 {
4526  int i = ( ( (int)size ) << 1 ) - 1;
4527  int j = (int)size - 1;
4528 
4529  while ( i >= 0 )
4530  {
4531  int y = grey16[i--];
4532  grey[j--] = static_cast< unsigned char >( ( y + ( grey16[i--] << 8 ) ) >> 8 );
4533  }
4534 }
4535 
4547 void
4548 vpImageConvert::MONO16ToRGBa( unsigned char *grey16, unsigned char *rgba, unsigned int size )
4549 {
4550  int i = ( ( (int)size ) << 1 ) - 1;
4551  int j = (int)( size * 4 - 1 );
4552 
4553  while ( i >= 0 )
4554  {
4555  int y = grey16[i--];
4556  unsigned char v = static_cast< unsigned char >( ( y + ( grey16[i--] << 8 ) ) >> 8 );
4557  rgba[j--] = vpRGBa::alpha_default;
4558  rgba[j--] = v;
4559  rgba[j--] = v;
4560  rgba[j--] = v;
4561  }
4562 }
4563 
4574 void
4575 vpImageConvert::HSV2RGB( const double *hue_, const double *saturation_, const double *value_, unsigned char *rgb,
4576  unsigned int size, unsigned int step )
4577 {
4578  for ( unsigned int i = 0; i < size; i++ )
4579  {
4580  double hue = hue_[i], saturation = saturation_[i], value = value_[i];
4581 
4582  if ( vpMath::equal( saturation, 0.0, std::numeric_limits< double >::epsilon() ) )
4583  {
4584  hue = value;
4585  saturation = value;
4586  }
4587  else
4588  {
4589  double h = hue * 6.0;
4590  double s = saturation;
4591  double v = value;
4592 
4593  if ( vpMath::equal( h, 6.0, std::numeric_limits< double >::epsilon() ) )
4594  {
4595  h = 0.0;
4596  }
4597 
4598  double f = h - (int)h;
4599  double p = v * ( 1.0 - s );
4600  double q = v * ( 1.0 - s * f );
4601  double t = v * ( 1.0 - s * ( 1.0 - f ) );
4602 
4603  switch ( (int)h )
4604  {
4605  case 0:
4606  hue = v;
4607  saturation = t;
4608  value = p;
4609  break;
4610 
4611  case 1:
4612  hue = q;
4613  saturation = v;
4614  value = p;
4615  break;
4616 
4617  case 2:
4618  hue = p;
4619  saturation = v;
4620  value = t;
4621  break;
4622 
4623  case 3:
4624  hue = p;
4625  saturation = q;
4626  value = v;
4627  break;
4628 
4629  case 4:
4630  hue = t;
4631  saturation = p;
4632  value = v;
4633  break;
4634 
4635  default: // case 5:
4636  hue = v;
4637  saturation = p;
4638  value = q;
4639  break;
4640  }
4641  }
4642 
4643  rgb[i * step] = (unsigned char)vpMath::round( hue * 255.0 );
4644  rgb[i * step + 1] = (unsigned char)vpMath::round( saturation * 255.0 );
4645  rgb[i * step + 2] = (unsigned char)vpMath::round( value * 255.0 );
4646  if ( step == 4 ) // alpha
4647  rgb[i * step + 3] = vpRGBa::alpha_default;
4648  }
4649 }
4650 
4661 void
4662 vpImageConvert::RGB2HSV( const unsigned char *rgb, double *hue, double *saturation, double *value, unsigned int size,
4663  unsigned int step )
4664 {
4665  for ( unsigned int i = 0; i < size; i++ )
4666  {
4667  double red, green, blue;
4668  double h, s, v;
4669  double min, max;
4670 
4671  red = rgb[i * step] / 255.0;
4672  green = rgb[i * step + 1] / 255.0;
4673  blue = rgb[i * step + 2] / 255.0;
4674 
4675  if ( red > green )
4676  {
4677  max = ( ( std::max ) )( red, blue );
4678  min = ( ( std::min ) )( green, blue );
4679  }
4680  else
4681  {
4682  max = ( ( std::max ) )( green, blue );
4683  min = ( ( std::min ) )( red, blue );
4684  }
4685 
4686  v = max;
4687 
4688  if ( !vpMath::equal( max, 0.0, std::numeric_limits< double >::epsilon() ) )
4689  {
4690  s = ( max - min ) / max;
4691  }
4692  else
4693  {
4694  s = 0.0;
4695  }
4696 
4697  if ( vpMath::equal( s, 0.0, std::numeric_limits< double >::epsilon() ) )
4698  {
4699  h = 0.0;
4700  }
4701  else
4702  {
4703  double delta = max - min;
4704  if ( vpMath::equal( delta, 0.0, std::numeric_limits< double >::epsilon() ) )
4705  {
4706  delta = 1.0;
4707  }
4708 
4709  if ( vpMath::equal( red, max, std::numeric_limits< double >::epsilon() ) )
4710  {
4711  h = ( green - blue ) / delta;
4712  }
4713  else if ( vpMath::equal( green, max, std::numeric_limits< double >::epsilon() ) )
4714  {
4715  h = 2 + ( blue - red ) / delta;
4716  }
4717  else
4718  {
4719  h = 4 + ( red - green ) / delta;
4720  }
4721 
4722  h /= 6.0;
4723  if ( h < 0.0 )
4724  {
4725  h += 1.0;
4726  }
4727  else if ( h > 1.0 )
4728  {
4729  h -= 1.0;
4730  }
4731  }
4732 
4733  hue[i] = h;
4734  saturation[i] = s;
4735  value[i] = v;
4736  }
4737 }
4738 
4751 void
4752 vpImageConvert::HSVToRGBa( const double *hue, const double *saturation, const double *value, unsigned char *rgba,
4753  unsigned int size )
4754 {
4755  vpImageConvert::HSV2RGB( hue, saturation, value, rgba, size, 4 );
4756 }
4757 
4770 void
4771 vpImageConvert::HSVToRGBa( const unsigned char *hue, const unsigned char *saturation, const unsigned char *value,
4772  unsigned char *rgba, unsigned int size )
4773 {
4774  for ( unsigned int i = 0; i < size; i++ )
4775  {
4776  double h = hue[i] / 255.0, s = saturation[i] / 255.0, v = value[i] / 255.0;
4777 
4778  vpImageConvert::HSVToRGBa( &h, &s, &v, ( rgba + i * 4 ), 1 );
4779  }
4780 }
4781 
4794 void
4795 vpImageConvert::RGBaToHSV( const unsigned char *rgba, double *hue, double *saturation, double *value,
4796  unsigned int size )
4797 {
4798  vpImageConvert::RGB2HSV( rgba, hue, saturation, value, size, 4 );
4799 }
4800 
4812 void
4813 vpImageConvert::RGBaToHSV( const unsigned char *rgba, unsigned char *hue, unsigned char *saturation,
4814  unsigned char *value, unsigned int size )
4815 {
4816  for ( unsigned int i = 0; i < size; i++ )
4817  {
4818  double h, s, v;
4819  vpImageConvert::RGBaToHSV( ( rgba + i * 4 ), &h, &s, &v, 1 );
4820 
4821  hue[i] = (unsigned char)( 255.0 * h );
4822  saturation[i] = (unsigned char)( 255.0 * s );
4823  value[i] = (unsigned char)( 255.0 * v );
4824  }
4825 }
4826 
4837 void
4838 vpImageConvert::HSVToRGB( const double *hue, const double *saturation, const double *value, unsigned char *rgb,
4839  unsigned int size )
4840 {
4841  vpImageConvert::HSV2RGB( hue, saturation, value, rgb, size, 3 );
4842 }
4843 
4854 void
4855 vpImageConvert::HSVToRGB( const unsigned char *hue, const unsigned char *saturation, const unsigned char *value,
4856  unsigned char *rgb, unsigned int size )
4857 {
4858  for ( unsigned int i = 0; i < size; i++ )
4859  {
4860  double h = hue[i] / 255.0, s = saturation[i] / 255.0, v = value[i] / 255.0;
4861 
4862  vpImageConvert::HSVToRGB( &h, &s, &v, ( rgb + i * 3 ), 1 );
4863  }
4864 }
4865 
4877 void
4878 vpImageConvert::RGBToHSV( const unsigned char *rgb, double *hue, double *saturation, double *value, unsigned int size )
4879 {
4880  vpImageConvert::RGB2HSV( rgb, hue, saturation, value, size, 3 );
4881 }
4882 
4893 void
4894 vpImageConvert::RGBToHSV( const unsigned char *rgb, unsigned char *hue, unsigned char *saturation, unsigned char *value,
4895  unsigned int size )
4896 {
4897  for ( unsigned int i = 0; i < size; i++ )
4898  {
4899  double h, s, v;
4900 
4901  vpImageConvert::RGBToHSV( ( rgb + i * 3 ), &h, &s, &v, 1 );
4902 
4903  hue[i] = (unsigned char)( 255.0 * h );
4904  saturation[i] = (unsigned char)( 255.0 * s );
4905  value[i] = (unsigned char)( 255.0 * v );
4906  }
4907 }
4908 
4909 // Bilinear
4910 
4923 void
4924 vpImageConvert::demosaicBGGRToRGBaBilinear( const uint8_t *bggr, uint8_t *rgba, unsigned int width, unsigned int height,
4925  unsigned int nThreads )
4926 {
4927  demosaicBGGRToRGBaBilinearTpl( bggr, rgba, width, height, nThreads );
4928 }
4929 
4942 void
4943 vpImageConvert::demosaicBGGRToRGBaBilinear( const uint16_t *bggr, uint16_t *rgba, unsigned int width,
4944  unsigned int height, unsigned int nThreads )
4945 {
4946  demosaicBGGRToRGBaBilinearTpl( bggr, rgba, width, height, nThreads );
4947 }
4948 
4961 void
4962 vpImageConvert::demosaicGBRGToRGBaBilinear( const uint8_t *gbrg, uint8_t *rgba, unsigned int width, unsigned int height,
4963  unsigned int nThreads )
4964 {
4965  demosaicGBRGToRGBaBilinearTpl( gbrg, rgba, width, height, nThreads );
4966 }
4967 
4980 void
4981 vpImageConvert::demosaicGBRGToRGBaBilinear( const uint16_t *gbrg, uint16_t *rgba, unsigned int width,
4982  unsigned int height, unsigned int nThreads )
4983 {
4984  demosaicGBRGToRGBaBilinearTpl( gbrg, rgba, width, height, nThreads );
4985 }
4986 
4999 void
5000 vpImageConvert::demosaicGRBGToRGBaBilinear( const uint8_t *grbg, uint8_t *rgba, unsigned int width, unsigned int height,
5001  unsigned int nThreads )
5002 {
5003  demosaicGRBGToRGBaBilinearTpl( grbg, rgba, width, height, nThreads );
5004 }
5005 
5018 void
5019 vpImageConvert::demosaicGRBGToRGBaBilinear( const uint16_t *grbg, uint16_t *rgba, unsigned int width,
5020  unsigned int height, unsigned int nThreads )
5021 {
5022  demosaicGRBGToRGBaBilinearTpl( grbg, rgba, width, height, nThreads );
5023 }
5024 
5037 void
5038 vpImageConvert::demosaicRGGBToRGBaBilinear( const uint8_t *rggb, uint8_t *rgba, unsigned int width, unsigned int height,
5039  unsigned int nThreads )
5040 {
5041  demosaicRGGBToRGBaBilinearTpl( rggb, rgba, width, height, nThreads );
5042 }
5043 
5056 void
5057 vpImageConvert::demosaicRGGBToRGBaBilinear( const uint16_t *rggb, uint16_t *rgba, unsigned int width,
5058  unsigned int height, unsigned int nThreads )
5059 {
5060  demosaicRGGBToRGBaBilinearTpl( rggb, rgba, width, height, nThreads );
5061 }
5062 
5063 // Malvar
5064 
5077 void
5078 vpImageConvert::demosaicBGGRToRGBaMalvar( const uint8_t *bggr, uint8_t *rgba, unsigned int width, unsigned int height,
5079  unsigned int nThreads )
5080 {
5081  demosaicBGGRToRGBaMalvarTpl( bggr, rgba, width, height, nThreads );
5082 }
5083 
5096 void
5097 vpImageConvert::demosaicBGGRToRGBaMalvar( const uint16_t *bggr, uint16_t *rgba, unsigned int width, unsigned int height,
5098  unsigned int nThreads )
5099 {
5100  demosaicBGGRToRGBaMalvarTpl( bggr, rgba, width, height, nThreads );
5101 }
5102 
5115 void
5116 vpImageConvert::demosaicGBRGToRGBaMalvar( const uint8_t *gbrg, uint8_t *rgba, unsigned int width, unsigned int height,
5117  unsigned int nThreads )
5118 {
5119  demosaicGBRGToRGBaMalvarTpl( gbrg, rgba, width, height, nThreads );
5120 }
5121 
5134 void
5135 vpImageConvert::demosaicGBRGToRGBaMalvar( const uint16_t *gbrg, uint16_t *rgba, unsigned int width, unsigned int height,
5136  unsigned int nThreads )
5137 {
5138  demosaicGBRGToRGBaMalvarTpl( gbrg, rgba, width, height, nThreads );
5139 }
5140 
5153 void
5154 vpImageConvert::demosaicGRBGToRGBaMalvar( const uint8_t *grbg, uint8_t *rgba, unsigned int width, unsigned int height,
5155  unsigned int nThreads )
5156 {
5157  demosaicGRBGToRGBaMalvarTpl( grbg, rgba, width, height, nThreads );
5158 }
5159 
5172 void
5173 vpImageConvert::demosaicGRBGToRGBaMalvar( const uint16_t *grbg, uint16_t *rgba, unsigned int width, unsigned int height,
5174  unsigned int nThreads )
5175 {
5176  demosaicGRBGToRGBaMalvarTpl( grbg, rgba, width, height, nThreads );
5177 }
5178 
5191 void
5192 vpImageConvert::demosaicRGGBToRGBaMalvar( const uint8_t *rggb, uint8_t *rgba, unsigned int width, unsigned int height,
5193  unsigned int nThreads )
5194 {
5195  demosaicRGGBToRGBaMalvarTpl( rggb, rgba, width, height, nThreads );
5196 }
5197 
5210 void
5211 vpImageConvert::demosaicRGGBToRGBaMalvar( const uint16_t *rggb, uint16_t *rgba, unsigned int width, unsigned int height,
5212  unsigned int nThreads )
5213 {
5214  demosaicRGGBToRGBaMalvarTpl( rggb, rgba, width, height, nThreads );
5215 }
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 demosaicBGGRToRGBaBilinear(const uint8_t *bggr, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void demosaicRGGBToRGBaMalvar(const uint8_t *rggb, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:800
static void HSVToRGB(const double *hue, const double *saturation, const double *value, unsigned char *rgb, unsigned int size)
unsigned char B
Blue component.
Definition: vpRGBa.h:150
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
unsigned int getRows() const
Definition: vpImage.h:218
static void RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value, unsigned int size)
Type * bitmap
points toward the bitmap
Definition: vpImage.h:143
static void MONO16ToGrey(unsigned char *grey16, unsigned char *grey, unsigned int size)
static bool equal(double x, double y, double s=0.001)
Definition: vpMath.h:295
static void YUV422ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
static void BGRaToRGBa(unsigned char *bgra, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static void YUV420ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
error that can be emited by ViSP classes.
Definition: vpException.h:71
static void YUV422ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
static void YCbCrToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void YUV411ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int size)
static void split(const vpImage< vpRGBa > &src, vpImage< unsigned char > *pR, vpImage< unsigned char > *pG, vpImage< unsigned char > *pB, vpImage< unsigned char > *pa=NULL)
static void YUVToRGB(unsigned char y, unsigned char u, unsigned char v, unsigned char &r, unsigned char &g, unsigned char &b)
static void demosaicGRBGToRGBaBilinear(const uint8_t *grbg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
unsigned char G
Green component.
Definition: vpRGBa.h:149
static void GreyToRGB(unsigned char *grey, unsigned char *rgb, unsigned int size)
static void RGBToHSV(const unsigned char *rgb, double *hue, double *saturation, double *value, unsigned int size)
Definition: vpRGBa.h:66
static void YUV444ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
static void GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int width, unsigned int height)
static void YUV420ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YVU9ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YUV422ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void YCrCbToRGB(unsigned char *ycrcb, unsigned char *rgb, unsigned int size)
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false)
static void YCrCbToRGBa(unsigned char *ycrcb, unsigned char *rgb, unsigned int size)
static void YVU9ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
static void YV12ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int width, unsigned int height)
static void demosaicGBRGToRGBaBilinear(const uint8_t *gbrg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void YCbCrToGrey(unsigned char *ycbcr, unsigned char *grey, unsigned int size)
unsigned int getCols() const
Definition: vpImage.h:179
unsigned char A
Additionnal component.
Definition: vpRGBa.h:151
static void YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
static void MONO16ToRGBa(unsigned char *grey16, unsigned char *rgba, unsigned int size)
static void RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void demosaicRGGBToRGBaBilinear(const uint8_t *rggb, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void demosaicGRBGToRGBaMalvar(const uint8_t *grbg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void demosaicBGGRToRGBaMalvar(const uint8_t *bggr, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void HSVToRGBa(const double *hue, const double *saturation, const double *value, unsigned char *rgba, unsigned int size)
static void merge(const vpImage< unsigned char > *R, const vpImage< unsigned char > *G, const vpImage< unsigned char > *B, const vpImage< unsigned char > *a, vpImage< vpRGBa > &RGBa)
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static int round(double x)
Definition: vpMath.h:247
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 BGRaToGrey(unsigned char *bgra, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static void YUV444ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
unsigned int getHeight() const
Definition: vpImage.h:188
static void YUV411ToRGBa(unsigned char *yuv, unsigned char *rgba, unsigned int size)
unsigned int getSize() const
Definition: vpImage.h:227
unsigned char R
Red component.
Definition: vpRGBa.h:148
#define vpDEBUG_TRACE
Definition: vpDebug.h:487
static void YCbCrToRGBa(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void YUV411ToGrey(unsigned char *yuv, unsigned char *grey, unsigned int size)
static void RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
static void demosaicGBRGToRGBaMalvar(const uint8_t *gbrg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
unsigned int getWidth() const
Definition: vpImage.h:246
static void createDepthHistogram(const vpImage< uint16_t > &src_depth, vpImage< vpRGBa > &dest_rgba)
void getMinMaxValue(Type &min, Type &max) const
Look for the minimum and the maximum value within the bitmap.
Definition: vpImage.h:938
static void YV12ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
static void YUV420ToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)