Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpImageConvert.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Convert image types.
32 */
33
38
39#include <map>
40#include <sstream>
41
42#if defined(_OPENMP)
43#include <omp.h>
44#endif
45
46
47#include <visp3/core/vpConfig.h>
48
49#ifndef VISP_SKIP_BAYER_CONVERSION
50#include "private/vpBayerConversion.h"
51#endif
52#include "private/vpImageConvert_impl.h"
53#if defined(VISP_HAVE_SIMDLIB)
54#include <Simd/SimdLib.h>
55#endif
56#include <visp3/core/vpImageConvert.h>
57
59bool vpImageConvert::YCbCrLUTcomputed = false;
60int vpImageConvert::vpCrr[256];
61int vpImageConvert::vpCgb[256];
62int vpImageConvert::vpCgr[256];
63int vpImageConvert::vpCbb[256];
64
74{
75 dest.resize(src.getHeight(), src.getWidth());
76
77 GreyToRGBa(src.bitmap, reinterpret_cast<unsigned char *>(dest.bitmap), src.getWidth(), src.getHeight());
78}
79
89void vpImageConvert::convert(const vpImage<vpRGBa> &src, vpImage<unsigned char> &dest, unsigned int nThreads)
90{
91 dest.resize(src.getHeight(), src.getWidth());
92
93 RGBaToGrey(reinterpret_cast<unsigned char *>(src.bitmap), dest.bitmap, src.getWidth(), src.getHeight(), nThreads);
94}
95
103{
104 dest.resize(src.getHeight(), src.getWidth());
105 unsigned int max_xy = src.getWidth() * src.getHeight();
106 float min, max;
107
108 src.getMinMaxValue(min, max);
109
110 const unsigned char var_uc_255 = 255;
111 for (unsigned int i = 0; i < max_xy; ++i) {
112 float val = 255.f * ((src.bitmap[i] - min) / (max - min));
113 if (val < 0) {
114 dest.bitmap[i] = 0;
115 }
116 else if (val > 255.f) {
117 dest.bitmap[i] = var_uc_255;
118 }
119 else {
120 dest.bitmap[i] = static_cast<unsigned char>(val);
121 }
122 }
123}
124
132{
133 const unsigned int srcHeight = src.getHeight(), srcWidth = src.getWidth();
134 dest.resize(src.getHeight(), src.getWidth());
135 vpRGBf min, max;
136 src.getMinMaxValue(min, max);
137
138 const unsigned int val_3 = 3;
139 const unsigned char var_uc_255 = 255;
140 for (unsigned int i = 0; i < srcHeight; ++i) {
141 for (unsigned int j = 0; j < srcWidth; ++j) {
142 for (unsigned int c = 0; c < val_3; ++c) {
143 float val = 255.f * ((reinterpret_cast<const float *>(&(src[i][j]))[c] - reinterpret_cast<float *>(&min)[c]) /
144 (reinterpret_cast<float *>(&max)[c] - reinterpret_cast<float *>(&min)[c]));
145 if (val < 0) {
146 reinterpret_cast<unsigned char *>(&(dest[i][j]))[c] = 0;
147 }
148 else if (val > 255.f) {
149 reinterpret_cast<unsigned char *>(&(dest[i][j]))[c] = var_uc_255;
150 }
151 else {
152 reinterpret_cast<unsigned char *>(&(dest[i][j]))[c] = static_cast<unsigned char>(val);
153 }
154 }
155 }
156 }
157}
158
165{
166 const unsigned int srcHeight = src.getHeight(), srcWidth = src.getWidth();
167 const unsigned int srcSize = srcHeight * srcWidth;
168 dest.resize(srcHeight, srcWidth);
169 for (unsigned int i = 0; i < srcSize; ++i) {
170 dest.bitmap[i] = static_cast<float>(src.bitmap[i]);
171 }
172}
173
181{
182 dest.resize(src.getHeight(), src.getWidth());
183 unsigned int max_xy = src.getWidth() * src.getHeight();
184 double min, max;
185
186 src.getMinMaxValue(min, max);
187
188 const unsigned char var_uc_255 = 255;
189 for (unsigned int i = 0; i < max_xy; ++i) {
190 double val = 255. * ((src.bitmap[i] - min) / (max - min));
191 if (val < 0) {
192 dest.bitmap[i] = 0;
193 }
194 else if (val > 255.0) {
195 dest.bitmap[i] = var_uc_255;
196 }
197 else {
198 dest.bitmap[i] = static_cast<unsigned char>(val);
199 }
200 }
201}
202
209void vpImageConvert::convert(const vpImage<uint16_t> &src, vpImage<unsigned char> &dest, unsigned char bitshift)
210{
211 const unsigned int srcSize = src.getSize();
212 dest.resize(src.getHeight(), src.getWidth());
213
214 for (unsigned int i = 0; i < srcSize; ++i) {
215 dest.bitmap[i] = static_cast<unsigned char>(src.bitmap[i] >> bitshift);
216 }
217}
218
225void vpImageConvert::convert(const vpImage<unsigned char> &src, vpImage<uint16_t> &dest, unsigned char bitshift)
226{
227 const unsigned int srcSize = src.getSize();
228 dest.resize(src.getHeight(), src.getWidth());
229
230 for (unsigned int i = 0; i < srcSize; ++i) {
231 dest.bitmap[i] = static_cast<unsigned char>(src.bitmap[i] << bitshift);
232 }
233}
234
241{
242 const unsigned int srcHeight = src.getHeight(), srcWidth = src.getWidth();
243 const unsigned int srcSize = srcHeight * srcWidth;
244 dest.resize(srcHeight, srcWidth);
245 for (unsigned int i = 0; i < srcSize; ++i) {
246 dest.bitmap[i] = static_cast<double>(src.bitmap[i]);
247 }
248}
249
258{
259 vp_createDepthHistogram(src_depth, dest_rgba);
260}
261
269{
270 vp_createDepthHistogram(src_depth, dest_depth);
271}
272
281{
282 vp_createDepthHistogram(src_depth, dest_rgba);
283}
284
292{
293 vp_createDepthHistogram(src_depth, dest_depth);
294}
295
305void vpImageConvert::RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
306{
307 RGBToRGBa(rgb, rgba, size, 1, false);
308}
309
326void vpImageConvert::RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int width, unsigned int height,
327 bool flip)
328{
329#if defined(VISP_HAVE_SIMDLIB)
330 if (!flip) {
331 SimdBgrToBgra(rgb, width, height, width * 3, rgba, width * 4, vpRGBa::alpha_default);
332 }
333 else {
334#endif
335 // if we have to flip the image, we start from the end last scanline so the
336 // step is negative
337 int lineStep = flip ? -static_cast<int>(width * 3) : static_cast<int>(width * 3);
338
339 // starting source address = last line if we need to flip the image
340 unsigned char *src = flip ? (rgb + (width * height * 3) + lineStep) : rgb;
341
342 unsigned int j = 0;
343 unsigned int i = 0;
344
345 for (i = 0; i < height; ++i) {
346 unsigned char *line = src;
347 for (j = 0; j < width; ++j) {
348 *rgba++ = *(++line);
349 *rgba++ = *(++line);
350 *rgba++ = *(++line);
351 *rgba++ = vpRGBa::alpha_default;
352 }
353 // go to the next line
354 src += lineStep;
355 }
356#if defined(VISP_HAVE_SIMDLIB)
357 }
358#endif
359}
360
373void vpImageConvert::RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
374{
375#if defined(VISP_HAVE_SIMDLIB)
376 SimdBgraToBgr(rgba, size, 1, size * 4, rgb, size * 3);
377#else
378 unsigned char *pt_input = rgba;
379 unsigned char *pt_end = rgba + (4 * size);
380 unsigned char *pt_output = rgb;
381
382 while (pt_input != pt_end) {
383 *(++pt_output) = *(++pt_input); // R
384 *(++pt_output) = *(++pt_input); // G
385 *(++pt_output) = *(++pt_input); // B
386 ++pt_input;
387 }
388#endif
389}
390
403void vpImageConvert::RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int size)
404{
405 RGBToGrey(rgb, grey, size, 1, false);
406}
407
422void vpImageConvert::RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height,
423 bool flip)
424{
425#if defined(VISP_HAVE_SIMDLIB)
426 if (!flip) {
427 SimdRgbToGray(rgb, width, height, width * 3, grey, width);
428 }
429 else {
430#endif
431 // if we have to flip the image, we start from the end last scanline so
432 // the step is negative
433 int lineStep = flip ? -static_cast<int>(width * 3) : static_cast<int>(width * 3);
434
435 // starting source address = last line if we need to flip the image
436 unsigned char *src = flip ? (rgb + (width * height * 3) + lineStep) : rgb;
437
438 unsigned int j = 0;
439 unsigned int i = 0;
440
441 unsigned r, g, b;
442
443 for (i = 0; i < height; ++i) {
444 unsigned char *line = src;
445 for (j = 0; j < width; ++j) {
446 r = *(++line);
447 g = *(++line);
448 b = *(++line);
449 *grey++ = static_cast<unsigned char>((0.2126 * r) + (0.7152 * g) + (0.0722 * b));
450 }
451
452 // go to the next line
453 src += lineStep;
454 }
455#if defined(VISP_HAVE_SIMDLIB)
456 }
457#endif
458}
459
475void vpImageConvert::RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int width, unsigned int height,
476 unsigned int nThreads)
477{
478#if !defined(_OPENMP) || !defined(VISP_HAVE_SIMDLIB)
479 (void)nThreads;
480#endif
481#if defined(VISP_HAVE_SIMDLIB)
482 const int heightAsInt = static_cast<int>(height);
483#if defined(_OPENMP)
484 if (nThreads > 0) {
485 omp_set_num_threads(static_cast<int>(nThreads));
486 }
487#pragma omp parallel for
488#endif
489 for (int i = 0; i < heightAsInt; ++i) {
490 unsigned int i_ = static_cast<unsigned int>(i);
491 SimdRgbaToGray(rgba + (i_ * width * 4), width, 1, width * 4, grey + (i_ * width), width);
492 }
493#endif
494 vpImageConvert::RGBaToGrey(rgba, grey, width * height);
495}
496
511void vpImageConvert::RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int size)
512{
513#if defined(VISP_HAVE_SIMDLIB)
514 SimdRgbaToGray(rgba, size, 1, size * 4, grey, size);
515#else
516 const unsigned int val_2 = 2;
517 const unsigned int val_4 = 4;
518 unsigned char *pt_input = rgba;
519 unsigned char *pt_end = rgba + (size * 4);
520 unsigned char *pt_output = grey;
521
522 while (pt_input != pt_end) {
523 *pt_output = static_cast<unsigned char>((0.2126 * (*pt_input)) + (0.7152 * (*(pt_input + 1))) + (0.0722 * (*(pt_input + val_2))));
524 pt_input += val_4;
525 ++pt_output;
526 }
527#endif
528}
529
542void vpImageConvert::GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int width, unsigned int height)
543{
544#if defined(VISP_HAVE_SIMDLIB)
545 SimdGrayToBgra(grey, width, height, width, rgba, width * sizeof(vpRGBa), vpRGBa::alpha_default);
546#else
547 vpImageConvert::GreyToRGBa(grey, rgba, width * height);
548#endif
549}
550
563void vpImageConvert::GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int size)
564{
565#if defined(VISP_HAVE_SIMDLIB)
566 GreyToRGBa(grey, rgba, size, 1);
567#else
568 const unsigned int val_2 = 2;
569 const unsigned int val_3 = 3;
570 const unsigned int val_4 = 4;
571 unsigned char *pt_input = grey;
572 unsigned char *pt_end = grey + size;
573 unsigned char *pt_output = rgba;
574
575 while (pt_input != pt_end) {
576 unsigned char p = *pt_input;
577 *pt_output = p; // R
578 *(pt_output + 1) = p; // G
579 *(pt_output + val_2) = p; // B
580 *(pt_output + val_3) = vpRGBa::alpha_default; // A
581
582 ++pt_input;
583 pt_output += val_4;
584 }
585#endif
586}
587
598void vpImageConvert::GreyToRGB(unsigned char *grey, unsigned char *rgb, unsigned int size)
599{
600#if defined(VISP_HAVE_SIMDLIB)
601 SimdGrayToBgr(grey, size, 1, size, rgb, size * 3);
602#else
603 const unsigned int val_2 = 2;
604 const unsigned int val_3 = 3;
605 unsigned char *pt_input = grey;
606 unsigned char *pt_end = grey + size;
607 unsigned char *pt_output = rgb;
608
609 while (pt_input != pt_end) {
610 unsigned char p = *pt_input;
611 *pt_output = p; // R
612 *(pt_output + 1) = p; // G
613 *(pt_output + val_2) = p; // B
614
615 ++pt_input;
616 pt_output += val_3;
617 }
618#endif
619}
620
637void vpImageConvert::BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height,
638 bool flip)
639{
640#if defined(VISP_HAVE_SIMDLIB)
641 if (!flip) {
642 SimdRgbToBgra(bgr, width, height, width * 3, rgba, width * sizeof(vpRGBa), vpRGBa::alpha_default);
643 }
644 else {
645#endif
646 // if we have to flip the image, we start from the end last scanline so the
647 // step is negative
648 const unsigned int val_2 = 2;
649 const unsigned int val_3 = 3;
650 int lineStep = flip ? -static_cast<int>(width * 3) : static_cast<int>(width * 3);
651
652 // starting source address = last line if we need to flip the image
653 unsigned char *src = flip ? (bgr + (width * height * 3) + lineStep) : bgr;
654
655 for (unsigned int i = 0; i < height; ++i) {
656 unsigned char *line = src;
657 for (unsigned int j = 0; j < width; ++j) {
658 *rgba++ = *(line + val_2);
659 *rgba++ = *(line + 1);
660 *rgba++ = *(line + 0);
661 *rgba++ = vpRGBa::alpha_default;
662
663 line += val_3;
664 }
665 // go to the next line
666 src += lineStep;
667 }
668#if defined(VISP_HAVE_SIMDLIB)
669 }
670#endif
671}
672
688void vpImageConvert::BGRaToRGBa(unsigned char *bgra, unsigned char *rgba, unsigned int width, unsigned int height,
689 bool flip)
690{
691#if defined(VISP_HAVE_SIMDLIB)
692 if (!flip) {
693 SimdBgraToRgba(bgra, width, height, width * 4, rgba, width * 4);
694 }
695 else {
696#endif
697 // if we have to flip the image, we start from the end last scanline so the
698 // step is negative
699 const unsigned int val_2 = 2;
700 const unsigned int val_3 = 3;
701 const unsigned int val_4 = 4;
702 int lineStep = flip ? -static_cast<int>(width * 4) : static_cast<int>(width * 4);
703
704 // starting source address = last line if we need to flip the image
705 unsigned char *src = flip ? (bgra + (width * height * val_4) + lineStep) : bgra;
706
707 for (unsigned int i = 0; i < height; ++i) {
708 unsigned char *line = src;
709 for (unsigned int j = 0; j < width; ++j) {
710 *rgba++ = *(line + val_2);
711 *rgba++ = *(line + 1);
712 *rgba++ = *(line + 0);
713 *rgba++ = *(line + val_3);
714
715 line += val_4;
716 }
717 // go to the next line
718 src += lineStep;
719 }
720#if defined(VISP_HAVE_SIMDLIB)
721 }
722#endif
723}
724
740void vpImageConvert::BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height,
741 bool flip, unsigned int nThreads)
742{
743#if !defined(_OPENMP) || !defined(VISP_HAVE_SIMDLIB)
744 (void)nThreads;
745#endif
746#if defined(VISP_HAVE_SIMDLIB)
747 const int heightAsInt = static_cast<int>(height);
748 if (!flip) {
749#if defined(_OPENMP)
750 if (nThreads > 0) {
751 omp_set_num_threads(static_cast<int>(nThreads));
752 }
753#pragma omp parallel for
754#endif
755 for (int i = 0; i < heightAsInt; ++i) {
756 unsigned int i_ = static_cast<unsigned int>(i);
757 SimdBgrToGray(bgr + (i_ * width * 3), width, 1, width * 3, grey + (i_ * width), width);
758 }
759 }
760 else {
761#endif
762 // if we have to flip the image, we start from the end last scan so
763 // the step is negative
764 const unsigned int val_2 = 2;
765 const unsigned int val_3 = 3;
766 int lineStep = flip ? -static_cast<int>(width * 3) : static_cast<int>(width * 3);
767
768 // starting source address = last line if we need to flip the image
769 unsigned char *src = flip ? (bgr + (width * height * 3) + lineStep) : bgr;
770
771 for (unsigned int i = 0; i < height; ++i) {
772 unsigned char *line = src;
773 for (unsigned int j = 0; j < width; ++j) {
774 *grey++ = static_cast<unsigned char>(static_cast<unsigned int>((0.2126 * *(line + val_2)) + (0.7152 * *(line + 1)) + (0.0722 * *(line + 0))));
775 line += val_3;
776 }
777
778 // go to the next line
779 src += lineStep;
780 }
781#if defined(VISP_HAVE_SIMDLIB)
782 }
783#endif
784}
785
801void vpImageConvert::BGRaToGrey(unsigned char *bgra, unsigned char *grey, unsigned int width, unsigned int height,
802 bool flip, unsigned int nThreads)
803{
804#if !defined(_OPENMP) || !defined(VISP_HAVE_SIMDLIB)
805 (void)nThreads;
806#endif
807#if defined(VISP_HAVE_SIMDLIB)
808 if (!flip) {
809 const int heightAsInt = static_cast<int>(height);
810#if defined(_OPENMP)
811 if (nThreads > 0) {
812 omp_set_num_threads(static_cast<int>(nThreads));
813 }
814#pragma omp parallel for
815#endif
816 for (int i = 0; i < heightAsInt; ++i) {
817 unsigned int i_ = static_cast<unsigned int>(i);
818 SimdBgraToGray(bgra + (i_ * width * 4), width, 1, width * 4, grey + (i_ * width), width);
819 }
820 }
821 else {
822#endif
823 // if we have to flip the image, we start from the end last scanline so
824 // the step is negative
825 const unsigned int val_2 = 2;
826 const unsigned int val_4 = 4;
827 int lineStep = flip ? -static_cast<int>(width * 4) : static_cast<int>(width * 4);
828
829 // starting source address = last line if we need to flip the image
830 unsigned char *src = flip ? (bgra + (width * height * 4) + lineStep) : bgra;
831
832 for (unsigned int i = 0; i < height; ++i) {
833 unsigned char *line = src;
834 for (unsigned int j = 0; j < width; ++j) {
835 *grey++ = static_cast<unsigned char>((0.2126 * *(line + val_2)) + (0.7152 * *(line + 1)) + (0.0722 * *(line + 0)));
836 line += val_4;
837 }
838
839 // go to the next line
840 src += lineStep;
841 }
842#if defined(VISP_HAVE_SIMDLIB)
843 }
844#endif
845}
846
850void vpImageConvert::computeYCbCrLUT()
851{
852 if (YCbCrLUTcomputed == false) {
853 const int val_256 = 256;
854 int index = 256;
855
856 while (index--) {
857
858 int aux = index - 128;
859 vpImageConvert::vpCrr[index] = static_cast<int>((364.6610 * aux) / val_256);
860 vpImageConvert::vpCgb[index] = static_cast<int>((-89.8779 * aux) / val_256);
861 vpImageConvert::vpCgr[index] = static_cast<int>((-185.8154 * aux) / val_256);
862 vpImageConvert::vpCbb[index] = static_cast<int>((460.5724 * aux) / val_256);
863 }
864
865 YCbCrLUTcomputed = true;
866 }
867}
868
890void vpImageConvert::YCbCrToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
891{
892 const unsigned int val_2 = 2;
893 const unsigned int val_3 = 3;
894 const int val_255 = 255;
895 const unsigned int val_255u = 255u;
896 unsigned char *cbv;
897 unsigned char *crv;
898 unsigned char *pt_ycbcr = ycbcr;
899 unsigned char *pt_rgb = rgb;
900 cbv = pt_ycbcr + 1;
901 crv = pt_ycbcr + val_3;
902
903 vpImageConvert::computeYCbCrLUT();
904
905 unsigned int col = 0;
906
907 while (size--) {
908 int val_r, val_g, val_b;
909 if (!(col % val_2)) {
910 cbv = pt_ycbcr + 1;
911 crv = pt_ycbcr + val_3;
912 }
913
914 val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
915 val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
916 val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
917
918 *pt_rgb++ = (val_r < 0) ? 0u : ((val_r > val_255) ? val_255u : static_cast<unsigned char>(val_r)); // Red component.
919 *pt_rgb++ = (val_g < 0) ? 0u : ((val_g > val_255) ? val_255u : static_cast<unsigned char>(val_g)); // Green component.
920 *pt_rgb++ = (val_b < 0) ? 0u : ((val_b > val_255) ? val_255u : static_cast<unsigned char>(val_b)); // Blue component.
921
922 pt_ycbcr += val_2;
923 ++col;
924 }
925}
926
952void vpImageConvert::YCbCrToRGBa(unsigned char *ycbcr, unsigned char *rgba, unsigned int size)
953{
954 const unsigned int val_2 = 2;
955 const unsigned int val_3 = 3;
956 const int val_255 = 255;
957 const unsigned int val_255u = 255u;
958 unsigned char *cbv;
959 unsigned char *crv;
960 unsigned char *pt_ycbcr = ycbcr;
961 unsigned char *pt_rgba = rgba;
962 cbv = pt_ycbcr + 1;
963 crv = pt_ycbcr + val_3;
964
965 vpImageConvert::computeYCbCrLUT();
966
967 unsigned int col = 0;
968
969 while (size--) {
970 int val_r, val_g, val_b;
971 if (!(col % val_2)) {
972 cbv = pt_ycbcr + 1;
973 crv = pt_ycbcr + val_3;
974 }
975
976 val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
977 val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
978 val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
979
980 *pt_rgba++ = (val_r < 0) ? 0u : ((val_r > val_255) ? val_255u : static_cast<unsigned char>(val_r)); // Red component.
981 *pt_rgba++ = (val_g < 0) ? 0u : ((val_g > val_255) ? val_255u : static_cast<unsigned char>(val_g)); // Green component.
982 *pt_rgba++ = (val_b < 0) ? 0u : ((val_b > val_255) ? val_255u : static_cast<unsigned char>(val_b)); // Blue component.
983 *pt_rgba++ = vpRGBa::alpha_default;
984
985 pt_ycbcr += val_2;
986 ++col;
987 }
988}
989
1009void vpImageConvert::YCbCrToGrey(unsigned char *ycbcr, unsigned char *grey, unsigned int size)
1010{
1011 const unsigned val_2 = 2;
1012 const unsigned val_4 = 4;
1013 unsigned int i = 0, j = 0;
1014 const unsigned int doubleSize = size * 2;
1015 while (j < doubleSize) {
1016 grey[i++] = ycbcr[j];
1017 grey[i++] = ycbcr[j + val_2];
1018 j += val_4;
1019 }
1020}
1021
1043void vpImageConvert::YCrCbToRGB(unsigned char *ycrcb, unsigned char *rgb, unsigned int size)
1044{
1045 const unsigned int val_2 = 2;
1046 const unsigned int val_3 = 3;
1047 const int val_255 = 255;
1048 const unsigned int val_255u = 255u;
1049 unsigned char *cbv;
1050 unsigned char *crv;
1051 unsigned char *pt_ycbcr = ycrcb;
1052 unsigned char *pt_rgb = rgb;
1053 crv = pt_ycbcr + 1;
1054 cbv = pt_ycbcr + val_3;
1055
1056 vpImageConvert::computeYCbCrLUT();
1057
1058 unsigned int col = 0;
1059
1060 while (size--) {
1061 int val_r, val_g, val_b;
1062 if (!(col % val_2)) {
1063 crv = pt_ycbcr + 1;
1064 cbv = pt_ycbcr + val_3;
1065 }
1066
1067 val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
1068 val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
1069 val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
1070
1071 *pt_rgb++ = (val_r < 0) ? 0u : ((val_r > val_255) ? val_255u : static_cast<unsigned char>(val_r)); // Red component.
1072 *pt_rgb++ = (val_g < 0) ? 0u : ((val_g > val_255) ? val_255u : static_cast<unsigned char>(val_g)); // Green component.
1073 *pt_rgb++ = (val_b < 0) ? 0u : ((val_b > val_255) ? val_255u : static_cast<unsigned char>(val_b)); // Blue component.
1074
1075 pt_ycbcr += val_2;
1076 ++col;
1077 }
1078}
1079
1104void vpImageConvert::YCrCbToRGBa(unsigned char *ycrcb, unsigned char *rgba, unsigned int size)
1105{
1106 const unsigned int val_2 = 2;
1107 const unsigned int val_3 = 3;
1108 const int val_255 = 255;
1109 const unsigned int val_255u = 255u;
1110 unsigned char *cbv;
1111 unsigned char *crv;
1112 unsigned char *pt_ycbcr = ycrcb;
1113 unsigned char *pt_rgba = rgba;
1114 crv = pt_ycbcr + 1;
1115 cbv = pt_ycbcr + val_3;
1116
1117 vpImageConvert::computeYCbCrLUT();
1118
1119 unsigned int col = 0;
1120
1121 while (size--) {
1122 int val_r, val_g, val_b;
1123 if (!(col % val_2)) {
1124 crv = pt_ycbcr + 1;
1125 cbv = pt_ycbcr + val_3;
1126 }
1127
1128 val_r = *pt_ycbcr + vpImageConvert::vpCrr[*crv];
1129 val_g = *pt_ycbcr + vpImageConvert::vpCgb[*cbv] + vpImageConvert::vpCgr[*crv];
1130 val_b = *pt_ycbcr + vpImageConvert::vpCbb[*cbv];
1131
1132 *pt_rgba++ = (val_r < 0) ? 0u : ((val_r > val_255) ? val_255u : static_cast<unsigned char>(val_r)); // Red component.
1133 *pt_rgba++ = (val_g < 0) ? 0u : ((val_g > val_255) ? val_255u : static_cast<unsigned char>(val_g)); // Green component.
1134 *pt_rgba++ = (val_b < 0) ? 0u : ((val_b > val_255) ? val_255u : static_cast<unsigned char>(val_b)); // Blue component.
1135 *pt_rgba++ = vpRGBa::alpha_default;
1136
1137 pt_ycbcr += val_2;
1138 ++col;
1139 }
1140}
1141
1186{
1187#if defined(VISP_HAVE_SIMDLIB)
1188 if (src.getSize() > 0) {
1189 if (pR) {
1190 pR->resize(src.getHeight(), src.getWidth());
1191 }
1192 if (pG) {
1193 pG->resize(src.getHeight(), src.getWidth());
1194 }
1195 if (pB) {
1196 pB->resize(src.getHeight(), src.getWidth());
1197 }
1198 if (pa) {
1199 pa->resize(src.getHeight(), src.getWidth());
1200 }
1201
1202 unsigned char *ptrR = pR ? pR->bitmap : new unsigned char[src.getSize()];
1203 unsigned char *ptrG = pG ? pG->bitmap : new unsigned char[src.getSize()];
1204 unsigned char *ptrB = pB ? pB->bitmap : new unsigned char[src.getSize()];
1205 unsigned char *ptrA = pa ? pa->bitmap : new unsigned char[src.getSize()];
1206
1207 SimdDeinterleaveBgra(reinterpret_cast<unsigned char *>(src.bitmap), src.getWidth() * sizeof(vpRGBa), src.getWidth(),
1208 src.getHeight(), ptrR, src.getWidth(), ptrG, src.getWidth(), ptrB, src.getWidth(), ptrA,
1209 src.getWidth());
1210
1211 if (!pR) {
1212 delete[] ptrR;
1213 }
1214 if (!pG) {
1215 delete[] ptrG;
1216 }
1217 if (!pB) {
1218 delete[] ptrB;
1219 }
1220 if (!pa) {
1221 delete[] ptrA;
1222 }
1223 }
1224#else
1225 size_t n = src.getNumberOfPixel();
1226 unsigned int height = src.getHeight();
1227 unsigned int width = src.getWidth();
1228 unsigned char *input;
1229 unsigned char *dst;
1230 const unsigned int index_0 = 0;
1231 const unsigned int index_1 = 1;
1232 const unsigned int index_2 = 2;
1233 const unsigned int index_3 = 3;
1234
1235 vpImage<unsigned char> *tabChannel[4];
1236
1237 tabChannel[index_0] = pR;
1238 tabChannel[index_1] = pG;
1239 tabChannel[index_2] = pB;
1240 tabChannel[index_3] = pa;
1241
1242 size_t i; /* ordre */
1243 const unsigned int val_3 = 3;
1244 const unsigned int val_4 = 4;
1245 for (unsigned int j = 0; j < val_4; ++j) {
1246 if (tabChannel[j] != nullptr) {
1247 if ((tabChannel[j]->getHeight() != height) || (tabChannel[j]->getWidth() != width)) {
1248 tabChannel[j]->resize(height, width);
1249 }
1250 dst = static_cast<unsigned char *>(tabChannel[j]->bitmap);
1251
1252 input = (unsigned char *)src.bitmap + j;
1253 i = 0;
1254 // optimization
1255 if (n >= val_4) {
1256 n -= val_3;
1257 for (; i < n; i += val_4) {
1258 *dst = *input;
1259 input += val_4;
1260 ++dst;
1261 *dst = *input;
1262 input += val_4;
1263 ++dst;
1264 *dst = *input;
1265 input += val_4;
1266 ++dst;
1267 *dst = *input;
1268 input += val_4;
1269 ++dst;
1270 }
1271 n += val_3;
1272 }
1273
1274 for (; i < n; ++i) {
1275 *dst = *input;
1276 input += val_4;
1277 ++dst;
1278 }
1279 }
1280 }
1281#endif
1282}
1283
1296{
1297 // Check if the input channels have all the same dimensions
1298 std::map<unsigned int, unsigned int> mapOfWidths, mapOfHeights;
1299 if (R != nullptr) {
1300 ++mapOfWidths[R->getWidth()];
1301 ++mapOfHeights[R->getHeight()];
1302 }
1303
1304 if (G != nullptr) {
1305 ++mapOfWidths[G->getWidth()];
1306 ++mapOfHeights[G->getHeight()];
1307 }
1308
1309 if (B != nullptr) {
1310 ++mapOfWidths[B->getWidth()];
1311 ++mapOfHeights[B->getHeight()];
1312 }
1313
1314 if (a != nullptr) {
1315 ++mapOfWidths[a->getWidth()];
1316 ++mapOfHeights[a->getHeight()];
1317 }
1318
1319 if ((mapOfWidths.size() == 1) && (mapOfHeights.size() == 1)) {
1320 unsigned int width = mapOfWidths.begin()->first;
1321 unsigned int height = mapOfHeights.begin()->first;
1322
1323 RGBa.resize(height, width);
1324
1325
1326#if defined(VISP_HAVE_SIMDLIB)
1327 if ((R != nullptr) && (G != nullptr) && (B != nullptr) && (a != nullptr)) {
1328 SimdInterleaveBgra(R->bitmap, width, G->bitmap, width, B->bitmap, width, a->bitmap, width, width, height,
1329 reinterpret_cast<uint8_t *>(RGBa.bitmap), width * sizeof(vpRGBa));
1330 }
1331 else {
1332#endif
1333 unsigned int size = width * height;
1334 for (unsigned int i = 0; i < size; ++i) {
1335 if (R != nullptr) {
1336 RGBa.bitmap[i].R = R->bitmap[i];
1337 }
1338
1339 if (G != nullptr) {
1340 RGBa.bitmap[i].G = G->bitmap[i];
1341 }
1342
1343 if (B != nullptr) {
1344 RGBa.bitmap[i].B = B->bitmap[i];
1345 }
1346
1347 if (a != nullptr) {
1348 RGBa.bitmap[i].A = a->bitmap[i];
1349 }
1350 }
1351#if defined(VISP_HAVE_SIMDLIB)
1352 }
1353#endif
1354 }
1355 else {
1356 throw vpException(vpException::dimensionError, "Mismatched dimensions!");
1357 }
1358}
1359
1370void vpImageConvert::MONO16ToGrey(unsigned char *grey16, unsigned char *grey, unsigned int size)
1371{
1372 const int val_256 = 256;
1373 int i = (static_cast<int>(size) * 2) - 1;
1374 int j = static_cast<int>(size) - 1;
1375
1376 while (i >= 0) {
1377 int y = grey16[i--];
1378 grey[j--] = static_cast<unsigned char>((y + (grey16[i] * val_256)) / val_256);
1379 --i;
1380 }
1381}
1382
1394void vpImageConvert::MONO16ToRGBa(unsigned char *grey16, unsigned char *rgba, unsigned int size)
1395{
1396 int i = (static_cast<int>(size) * 2) - 1;
1397 int j = (static_cast<int>(size) * 4) - 1;
1398
1399 while (i >= 0) {
1400 int y = grey16[i--];
1401 unsigned char v = static_cast<unsigned char>((y + (grey16[i] * 256)) / 256);
1402 --i;
1403 rgba[j--] = vpRGBa::alpha_default;
1404 rgba[j--] = v;
1405 rgba[j--] = v;
1406 rgba[j--] = v;
1407 }
1408}
1409
1410// Bilinear
1411#ifndef VISP_SKIP_BAYER_CONVERSION
1424void vpImageConvert::demosaicBGGRToRGBaBilinear(const uint8_t *bggr, uint8_t *rgba, unsigned int width,
1425 unsigned int height, unsigned int nThreads)
1426{
1427 demosaicBGGRToRGBaBilinearTpl(bggr, rgba, width, height, nThreads);
1428}
1429
1442void vpImageConvert::demosaicBGGRToRGBaBilinear(const uint16_t *bggr, uint16_t *rgba, unsigned int width,
1443 unsigned int height, unsigned int nThreads)
1444{
1445 demosaicBGGRToRGBaBilinearTpl(bggr, rgba, width, height, nThreads);
1446}
1447
1460void vpImageConvert::demosaicGBRGToRGBaBilinear(const uint8_t *gbrg, uint8_t *rgba, unsigned int width,
1461 unsigned int height, unsigned int nThreads)
1462{
1463 demosaicGBRGToRGBaBilinearTpl(gbrg, rgba, width, height, nThreads);
1464}
1465
1478void vpImageConvert::demosaicGBRGToRGBaBilinear(const uint16_t *gbrg, uint16_t *rgba, unsigned int width,
1479 unsigned int height, unsigned int nThreads)
1480{
1481 demosaicGBRGToRGBaBilinearTpl(gbrg, rgba, width, height, nThreads);
1482}
1483
1496void vpImageConvert::demosaicGRBGToRGBaBilinear(const uint8_t *grbg, uint8_t *rgba, unsigned int width,
1497 unsigned int height, unsigned int nThreads)
1498{
1499 demosaicGRBGToRGBaBilinearTpl(grbg, rgba, width, height, nThreads);
1500}
1501
1514void vpImageConvert::demosaicGRBGToRGBaBilinear(const uint16_t *grbg, uint16_t *rgba, unsigned int width,
1515 unsigned int height, unsigned int nThreads)
1516{
1517 demosaicGRBGToRGBaBilinearTpl(grbg, rgba, width, height, nThreads);
1518}
1519
1532void vpImageConvert::demosaicRGGBToRGBaBilinear(const uint8_t *rggb, uint8_t *rgba, unsigned int width,
1533 unsigned int height, unsigned int nThreads)
1534{
1535 demosaicRGGBToRGBaBilinearTpl(rggb, rgba, width, height, nThreads);
1536}
1537
1550void vpImageConvert::demosaicRGGBToRGBaBilinear(const uint16_t *rggb, uint16_t *rgba, unsigned int width,
1551 unsigned int height, unsigned int nThreads)
1552{
1553 demosaicRGGBToRGBaBilinearTpl(rggb, rgba, width, height, nThreads);
1554}
1555
1556// Malvar
1557
1570void vpImageConvert::demosaicBGGRToRGBaMalvar(const uint8_t *bggr, uint8_t *rgba, unsigned int width,
1571 unsigned int height, unsigned int nThreads)
1572{
1573 demosaicBGGRToRGBaMalvarTpl(bggr, rgba, width, height, nThreads);
1574}
1575
1588void vpImageConvert::demosaicBGGRToRGBaMalvar(const uint16_t *bggr, uint16_t *rgba, unsigned int width,
1589 unsigned int height, unsigned int nThreads)
1590{
1591 demosaicBGGRToRGBaMalvarTpl(bggr, rgba, width, height, nThreads);
1592}
1593
1606void vpImageConvert::demosaicGBRGToRGBaMalvar(const uint8_t *gbrg, uint8_t *rgba, unsigned int width,
1607 unsigned int height, unsigned int nThreads)
1608{
1609 demosaicGBRGToRGBaMalvarTpl(gbrg, rgba, width, height, nThreads);
1610}
1611
1624void vpImageConvert::demosaicGBRGToRGBaMalvar(const uint16_t *gbrg, uint16_t *rgba, unsigned int width,
1625 unsigned int height, unsigned int nThreads)
1626{
1627 demosaicGBRGToRGBaMalvarTpl(gbrg, rgba, width, height, nThreads);
1628}
1629
1642void vpImageConvert::demosaicGRBGToRGBaMalvar(const uint8_t *grbg, uint8_t *rgba, unsigned int width,
1643 unsigned int height, unsigned int nThreads)
1644{
1645 demosaicGRBGToRGBaMalvarTpl(grbg, rgba, width, height, nThreads);
1646}
1647
1660void vpImageConvert::demosaicGRBGToRGBaMalvar(const uint16_t *grbg, uint16_t *rgba, unsigned int width,
1661 unsigned int height, unsigned int nThreads)
1662{
1663 demosaicGRBGToRGBaMalvarTpl(grbg, rgba, width, height, nThreads);
1664}
1665
1678void vpImageConvert::demosaicRGGBToRGBaMalvar(const uint8_t *rggb, uint8_t *rgba, unsigned int width,
1679 unsigned int height, unsigned int nThreads)
1680{
1681 demosaicRGGBToRGBaMalvarTpl(rggb, rgba, width, height, nThreads);
1682}
1683
1696void vpImageConvert::demosaicRGGBToRGBaMalvar(const uint16_t *rggb, uint16_t *rgba, unsigned int width,
1697 unsigned int height, unsigned int nThreads)
1698{
1699 demosaicRGGBToRGBaMalvarTpl(rggb, rgba, width, height, nThreads);
1700}
1701#endif // VISP_SKIP_BAYER_CONVERSION
1702
1703END_VISP_NAMESPACE
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ dimensionError
Bad dimension.
Definition vpException.h:71
static void MONO16ToGrey(unsigned char *grey16, unsigned char *grey, unsigned int size)
static void demosaicBGGRToRGBaBilinear(const uint8_t *bggr, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void demosaicGRBGToRGBaBilinear(const uint8_t *grbg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void demosaicGRBGToRGBaMalvar(const uint8_t *grbg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void demosaicGBRGToRGBaMalvar(const uint8_t *gbrg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
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 demosaicBGGRToRGBaMalvar(const uint8_t *bggr, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void demosaicGBRGToRGBaBilinear(const uint8_t *gbrg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void YCbCrToGrey(unsigned char *ycbcr, unsigned char *grey, unsigned int size)
static void split(const vpImage< vpRGBa > &src, vpImage< unsigned char > *pR, vpImage< unsigned char > *pG, vpImage< unsigned char > *pB, vpImage< unsigned char > *pa=nullptr)
static void YCrCbToRGB(unsigned char *ycrcb, unsigned char *rgb, unsigned int size)
static void YCbCrToRGBa(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void createDepthHistogram(const vpImage< uint16_t > &src_depth, vpImage< vpRGBa > &dest_rgba)
static void demosaicRGGBToRGBaMalvar(const uint8_t *rggb, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int width, unsigned int height)
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static void MONO16ToRGBa(unsigned char *grey16, unsigned char *rgba, unsigned int size)
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false)
static void RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void GreyToRGB(unsigned char *grey, unsigned char *rgb, unsigned int size)
static void YCrCbToRGBa(unsigned char *ycrcb, unsigned char *rgb, unsigned int size)
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
static void YCbCrToRGB(unsigned char *ycbcr, unsigned char *rgb, unsigned int size)
static void BGRaToGrey(unsigned char *bgra, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static void BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static void demosaicRGGBToRGBaBilinear(const uint8_t *rggb, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void BGRaToRGBa(unsigned char *bgra, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static void RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
Definition of the vpImage class member functions.
Definition vpImage.h:131
unsigned int getWidth() const
Definition vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition vpImage.h:544
unsigned int getNumberOfPixel() const
Definition vpImage.h:203
unsigned int getSize() const
Definition vpImage.h:221
Type * bitmap
points toward the bitmap
Definition vpImage.h:135
unsigned int getHeight() const
Definition vpImage.h:181
void getMinMaxValue(Type &min, Type &max, bool onlyFiniteVal=true) const
Look for the minimum and the maximum value within the bitmap.
@ alpha_default
Definition vpRGBa.h:76