Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpImage_lut.h
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 * Image handling.
32 */
33
34#ifndef VP_IMAGE_LUT_H
35#define VP_IMAGE_LUT_H
36
37// Warning: this file shouldn't be included by the user. Internal usage only to reduce length of vpImage.h
38
39#if defined(VISP_HAVE_THREADS)
40namespace
41{
42struct vpImageLut_Param_t
43{
44 unsigned int m_start_index;
45 unsigned int m_end_index;
46
47 unsigned char m_lut[256];
48 unsigned char *m_bitmap;
49
50 vpImageLut_Param_t(unsigned int start_index, unsigned int end_index, unsigned char *bitmap)
51 : m_start_index(start_index), m_end_index(end_index), m_lut(), m_bitmap(bitmap)
52 { }
53};
54
55void performLutThread(vpImageLut_Param_t *imageLut_param)
56{
57 unsigned int start_index = imageLut_param->m_start_index;
58 unsigned int end_index = imageLut_param->m_end_index;
59
60 unsigned char *bitmap = imageLut_param->m_bitmap;
61
62 unsigned char *ptrStart = bitmap + start_index;
63 unsigned char *ptrEnd = bitmap + end_index;
64 unsigned char *ptrCurrent = ptrStart;
65
66 if (end_index - start_index >= 8) {
67 // Unroll loop version
68 for (; ptrCurrent <= ptrEnd - 8;) {
69 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
70 ++ptrCurrent;
71
72 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
73 ++ptrCurrent;
74
75 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
76 ++ptrCurrent;
77
78 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
79 ++ptrCurrent;
80
81 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
82 ++ptrCurrent;
83
84 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
85 ++ptrCurrent;
86
87 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
88 ++ptrCurrent;
89
90 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
91 ++ptrCurrent;
92 }
93 }
94
95 for (; ptrCurrent != ptrEnd; ++ptrCurrent) {
96 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
97 }
98}
99
100struct vpImageLutRGBa_Param_t
101{
102 unsigned int m_start_index;
103 unsigned int m_end_index;
104
105 VISP_NAMESPACE_ADDRESSING vpRGBa m_lut[256];
106 unsigned char *m_bitmap;
107
108 vpImageLutRGBa_Param_t(unsigned int start_index, unsigned int end_index, unsigned char *bitmap)
109 : m_start_index(start_index), m_end_index(end_index), m_lut(), m_bitmap(bitmap)
110 { }
111};
112
113void performLutRGBaThread(vpImageLutRGBa_Param_t *imageLut_param)
114{
115 unsigned int start_index = imageLut_param->m_start_index;
116 unsigned int end_index = imageLut_param->m_end_index;
117
118 unsigned char *bitmap = imageLut_param->m_bitmap;
119
120 unsigned char *ptrStart = bitmap + start_index * 4;
121 unsigned char *ptrEnd = bitmap + end_index * 4;
122 unsigned char *ptrCurrent = ptrStart;
123
124 if (end_index - start_index >= 4 * 2) {
125 // Unroll loop version
126 for (; ptrCurrent <= ptrEnd - 4 * 2;) {
127 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
128 ptrCurrent++;
129 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
130 ptrCurrent++;
131 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
132 ptrCurrent++;
133 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
134 ptrCurrent++;
135
136 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
137 ptrCurrent++;
138 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
139 ptrCurrent++;
140 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
141 ptrCurrent++;
142 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
143 ptrCurrent++;
144 }
145 }
146
147 while (ptrCurrent != ptrEnd) {
148 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
149 ptrCurrent++;
150
151 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
152 ptrCurrent++;
153
154 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
155 ptrCurrent++;
156
157 *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
158 ptrCurrent++;
159 }
160}
161} // namespace
162#endif
163
172template <class Type> void vpImage<Type>::performLut(const Type(&)[256], unsigned int)
173{
174 std::cerr << "Not implemented !" << std::endl;
175}
176
187template <> inline void vpImage<unsigned char>::performLut(const unsigned char(&lut)[256], unsigned int nbThreads)
188{
189 unsigned int size = getWidth() * getHeight();
190 unsigned char *ptrStart = static_cast<unsigned char *>(bitmap);
191 unsigned char *ptrEnd = ptrStart + size;
192 unsigned char *ptrCurrent = ptrStart;
193
194 bool use_single_thread = ((nbThreads == 0) || (nbThreads == 1));
195#if !defined(VISP_HAVE_THREADS)
196 use_single_thread = true;
197#endif
198
199 if ((!use_single_thread) && (getSize() <= nbThreads)) {
200 use_single_thread = true;
201 }
202
203 if (use_single_thread) {
204 // Single thread
205
206 while (ptrCurrent != ptrEnd) {
207 *ptrCurrent = lut[*ptrCurrent];
208 ++ptrCurrent;
209 }
210 }
211 else {
212#if defined(VISP_HAVE_THREADS)
213 // Multi-threads
214 std::vector<std::thread *> threadpool;
215 std::vector<vpImageLut_Param_t *> imageLutParams;
216
217 unsigned int image_size = getSize();
218 unsigned int step = image_size / nbThreads;
219 unsigned int last_step = image_size - step * (nbThreads - 1);
220
221 for (unsigned int index = 0; index < nbThreads; ++index) {
222 unsigned int start_index = index * step;
223 unsigned int end_index = (index + 1) * step;
224
225 if (index == nbThreads - 1) {
226 end_index = start_index + last_step;
227 }
228
229 vpImageLut_Param_t *imageLut_param = new vpImageLut_Param_t(start_index, end_index, bitmap);
230 memcpy(imageLut_param->m_lut, lut, 256 * sizeof(unsigned char));
231
232 imageLutParams.push_back(imageLut_param);
233
234 // Start the threads
235 std::thread *imageLut_thread = new std::thread(&performLutThread, imageLut_param);
236 threadpool.push_back(imageLut_thread);
237 }
238
239 for (size_t cpt = 0; cpt < threadpool.size(); ++cpt) {
240 // Wait until thread ends up
241 threadpool[cpt]->join();
242 }
243
244 // Delete
245 for (size_t cpt = 0; cpt < threadpool.size(); ++cpt) {
246 delete threadpool[cpt];
247 }
248
249 for (size_t cpt = 0; cpt < imageLutParams.size(); ++cpt) {
250 delete imageLutParams[cpt];
251 }
252#endif
253 }
254 }
255
266template <> inline void vpImage<vpRGBa>::performLut(const vpRGBa(&lut)[256], unsigned int nbThreads)
267{
268 unsigned int size = getWidth() * getHeight();
269 unsigned char *ptrStart = reinterpret_cast<unsigned char *>(bitmap);
270 unsigned char *ptrEnd = ptrStart + (size * 4);
271 unsigned char *ptrCurrent = ptrStart;
272
273 bool use_single_thread = ((nbThreads == 0) || (nbThreads == 1));
274#if !defined(VISP_HAVE_THREADS)
275 use_single_thread = true;
276#endif
277
278 if ((!use_single_thread) && (getSize() <= nbThreads)) {
279 use_single_thread = true;
280 }
281
282 if (use_single_thread) {
283 // Single thread
284 while (ptrCurrent != ptrEnd) {
285 *ptrCurrent = lut[*ptrCurrent].R;
286 ++ptrCurrent;
287
288 *ptrCurrent = lut[*ptrCurrent].G;
289 ++ptrCurrent;
290
291 *ptrCurrent = lut[*ptrCurrent].B;
292 ++ptrCurrent;
293
294 *ptrCurrent = lut[*ptrCurrent].A;
295 ++ptrCurrent;
296 }
297 }
298 else {
299#if defined(VISP_HAVE_THREADS)
300 // Multi-threads
301 std::vector<std::thread *> threadpool;
302 std::vector<vpImageLutRGBa_Param_t *> imageLutParams;
303
304 unsigned int image_size = getSize();
305 unsigned int step = image_size / nbThreads;
306 unsigned int last_step = image_size - step * (nbThreads - 1);
307
308 for (unsigned int index = 0; index < nbThreads; ++index) {
309 unsigned int start_index = index * step;
310 unsigned int end_index = (index + 1) * step;
311
312 if (index == nbThreads - 1) {
313 end_index = start_index + last_step;
314 }
315
316 vpImageLutRGBa_Param_t *imageLut_param = new vpImageLutRGBa_Param_t(start_index, end_index, reinterpret_cast<unsigned char *>(bitmap));
317 memcpy(static_cast<void *>(imageLut_param->m_lut), lut, 256 * sizeof(vpRGBa));
318
319 imageLutParams.push_back(imageLut_param);
320
321 // Start the threads
322 std::thread *imageLut_thread = new std::thread(&performLutRGBaThread, imageLut_param);
323 threadpool.push_back(imageLut_thread);
324 }
325
326 for (size_t cpt = 0; cpt < threadpool.size(); ++cpt) {
327 // Wait until thread ends up
328 threadpool[cpt]->join();
329 }
330
331 // Delete
332 for (size_t cpt = 0; cpt < threadpool.size(); ++cpt) {
333 delete threadpool[cpt];
334 }
335
336 for (size_t cpt = 0; cpt < imageLutParams.size(); ++cpt) {
337 delete imageLutParams[cpt];
338 }
339#endif
340 }
341 }
342
343#endif
unsigned int getWidth() const
Definition vpImage.h:242
void performLut(const Type(&lut)[256], unsigned int nbThreads=1)
unsigned int getSize() const
Definition vpImage.h:221
vpRGBa * bitmap
Definition vpImage.h:135
unsigned int getHeight() const
Definition vpImage.h:181
unsigned char B
Blue component.
Definition vpRGBa.h:327
unsigned char R
Red component.
Definition vpRGBa.h:325
unsigned char G
Green component.
Definition vpRGBa.h:326
unsigned char A
Additional component.
Definition vpRGBa.h:328