conversion_utils.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * camera_aravis
4  *
5  * Copyright © 2022 Fraunhofer IOSB and contributors
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  ****************************************************************************/
23 
25 
26 #include <ros/ros.h>
27 
28 namespace camera_aravis
29 {
30 
31 void renameImg(sensor_msgs::ImagePtr& in, sensor_msgs::ImagePtr& out, const std::string out_format) {
32  if (!in) {
33  ROS_WARN("camera_aravis::renameImg(): no input image given.");
34  return;
35  }
36 
37  // make a shallow copy (in-place operation on input)
38  out = in;
39 
40  out->encoding = out_format;
41 }
42 
43 void shift(uint16_t* data, const size_t length, const size_t digits) {
44  for (size_t i=0; i<length; ++i) {
45  data[i] <<= digits;
46  }
47 }
48 
49 void shiftImg(sensor_msgs::ImagePtr& in, sensor_msgs::ImagePtr& out, const size_t n_digits, const std::string out_format)
50 {
51  if (!in) {
52  ROS_WARN("camera_aravis::shiftImg(): no input image given.");
53  return;
54  }
55 
56  // make a shallow copy (in-place operation on input)
57  out = in;
58 
59  // shift
60  shift(reinterpret_cast<uint16_t*>(out->data.data()), out->data.size()/2, n_digits);
61  out->encoding = out_format;
62 }
63 
64 void interleaveImg(sensor_msgs::ImagePtr& in, sensor_msgs::ImagePtr& out, const size_t n_digits, const std::string out_format)
65 {
66  if (!in) {
67  ROS_WARN("camera_aravis::interleaveImg(): no input image given.");
68  return;
69  }
70 
71  if (!out) {
72  out.reset(new sensor_msgs::Image);
73  ROS_INFO("camera_aravis::interleaveImg(): no output image given. Reserved a new one.");
74  }
75 
76  out->header = in->header;
77  out->height = in->height;
78  out->width = in->width;
79  out->is_bigendian = in->is_bigendian;
80  out->step = in->step;
81  out->data.resize(in->data.size());
82 
83  const size_t n_bytes = in->data.size() / (3 * in->width * in->height);
84  uint8_t* c0 = in->data.data();
85  uint8_t* c1 = in->data.data() + (in->data.size() / 3);
86  uint8_t* c2 = in->data.data() + (2 * in->data.size() / 3);
87  uint8_t* o = out->data.data();
88 
89  for (uint32_t h=0; h<in->height; ++h) {
90  for (uint32_t w=0; w<in->width; ++w) {
91  for (size_t i=0; i<n_bytes; ++i) {
92  o[i] = c0[i];
93  o[i+n_bytes] = c1[i];
94  o[i+2*n_bytes] = c2[i];
95  }
96  c0 += n_bytes;
97  c1 += n_bytes;
98  c2 += n_bytes;
99  o += 3*n_bytes;
100  }
101  }
102 
103  if (n_digits>0) {
104  shift(reinterpret_cast<uint16_t*>(out->data.data()), out->data.size()/2, n_digits);
105  }
106  out->encoding = out_format;
107 }
108 
109 void unpack10p32Img(sensor_msgs::ImagePtr& in, sensor_msgs::ImagePtr& out, const std::string out_format) {
110  if (!in) {
111  ROS_WARN("camera_aravis::unpack10pImg(): no input image given.");
112  return;
113  }
114 
115  if (!out) {
116  out.reset(new sensor_msgs::Image);
117  ROS_INFO("camera_aravis::unpack10pImg(): no output image given. Reserved a new one.");
118  }
119 
120  out->header = in->header;
121  out->height = in->height;
122  out->width = in->width;
123  out->is_bigendian = in->is_bigendian;
124  out->step = (3*in->step)/2;
125  out->data.resize((3*in->data.size())/2);
126 
127  // change pixel bit alignment from every 3*10+2 = 32 Bit = 4 Byte format LSB
128  // byte 3 | byte 2 | byte 1 | byte 0
129  // 00CCCCCC CCCCBBBB BBBBBBAA AAAAAAAA
130  // into 3*16 = 48 Bit = 6 Byte format
131  // bytes 5+4 | bytes 3+2 | bytes 1+0
132  // CCCCCCCC CC000000 BBBBBBBB BB000000 AAAAAAAA AA000000
133 
134  uint8_t* from = in->data.data();
135  uint16_t* to = reinterpret_cast<uint16_t*>(out->data.data());
136  // unpack a full RGB pixel per iteration
137  for (size_t i=0; i<in->data.size()/4; ++i) {
138 
139  std::memcpy(to, from, 2);
140  to[0] <<= 6;
141 
142  std::memcpy(&to[1], &from[1], 2);
143  to[1] <<= 4;
144  to[1] &= 0b1111111111000000;
145 
146  std::memcpy(&to[2], &from[2], 2);
147  to[2] <<= 2;
148  to[2] &= 0b1111111111000000;
149 
150  to+=3;
151  from+=4;
152  }
153 
154  out->encoding = out_format;
155 }
156 
157 void unpack10PackedImg(sensor_msgs::ImagePtr& in, sensor_msgs::ImagePtr& out, const std::string out_format) {
158  if (!in) {
159  ROS_WARN("camera_aravis::unpack10pImg(): no input image given.");
160  return;
161  }
162 
163  if (!out) {
164  out.reset(new sensor_msgs::Image);
165  ROS_INFO("camera_aravis::unpack10pImg(): no output image given. Reserved a new one.");
166  }
167 
168  out->header = in->header;
169  out->height = in->height;
170  out->width = in->width;
171  out->is_bigendian = in->is_bigendian;
172  out->step = (3*in->step)/2;
173  out->data.resize((3*in->data.size())/2);
174 
175  // change pixel bit alignment from every 3*10+2 = 32 Bit = 4 Byte format
176  // byte 3 | byte 2 | byte 1 | byte 0
177  // AAAAAAAA BBBBBBBB CCCCCCCC 00CCBBAA
178  // into 3*16 = 48 Bit = 6 Byte format
179  // bytes 5+4 | bytes 3+2 | bytes 1+0
180  // CCCCCCCC CC000000 BBBBBBBB BB000000 AAAAAAAA AA000000
181 
182  // note that in this old style GigE format, byte 0 contains the lsb of C, B as well as A
183 
184  uint8_t* from = in->data.data();
185  uint8_t* to = out->data.data();
186  // unpack a RGB pixel per iteration
187  for (size_t i=0; i<in->data.size()/4; ++i) {
188 
189  to[0] = from[0]<<6;
190  to[1] = from[3];
191  to[2] = (from[0] & 0b00001100)<<4;
192  to[3] = from[2];
193  to[4] = (from[0] & 0b00110000)<<2;
194  to[5] = from[1];
195 
196  to+=6;
197  from+=4;
198  }
199  out->encoding = out_format;
200 }
201 
202 
203 void unpack10pMonoImg(sensor_msgs::ImagePtr& in, sensor_msgs::ImagePtr& out, const std::string out_format) {
204  if (!in) {
205  ROS_WARN("camera_aravis::unpack10pImg(): no input image given.");
206  return;
207  }
208 
209  if (!out) {
210  out.reset(new sensor_msgs::Image);
211  ROS_INFO("camera_aravis::unpack10pImg(): no output image given. Reserved a new one.");
212  }
213 
214  out->header = in->header;
215  out->height = in->height;
216  out->width = in->width;
217  out->is_bigendian = in->is_bigendian;
218  out->step = (8*in->step)/5;
219  out->data.resize((8*in->data.size())/5);
220 
221  // change pixel bit alignment from every 4*10 = 40 Bit = 5 Byte format LSB
222  // byte 4 | byte 3 | byte 2 | byte 1 | byte 0
223  // DDDDDDDD DDCCCCCC CCCCBBBB BBBBBBAA AAAAAAAA
224  // into 4*16 = 64 Bit = 8 Byte format
225  // bytes 7+6 | bytes 5+4 | bytes 3+2 | bytes 1+0
226  // DDDDDDDD DD000000 CCCCCCCC CC000000 BBBBBBBB BB000000 AAAAAAAA AA000000
227 
228  uint8_t* from = in->data.data();
229  uint16_t* to = reinterpret_cast<uint16_t*>(out->data.data());
230  // unpack 4 mono pixels per iteration
231  for (size_t i=0; i<in->data.size()/5; ++i) {
232 
233  std::memcpy(to, from, 2);
234  to[0] <<= 6;
235 
236  std::memcpy(&to[1], &from[1], 2);
237  to[1] <<= 4;
238  to[1] &= 0b1111111111000000;
239 
240  std::memcpy(&to[2], &from[2], 2);
241  to[2] <<= 2;
242  to[2] &= 0b1111111111000000;
243 
244  std::memcpy(&to[3], &from[3], 2);
245  to[3] &= 0b1111111111000000;
246 
247  to+=4;
248  from+=5;
249  }
250  out->encoding = out_format;
251 }
252 
253 void unpack10PackedMonoImg(sensor_msgs::ImagePtr& in, sensor_msgs::ImagePtr& out, const std::string out_format) {
254  if (!in) {
255  ROS_WARN("camera_aravis::unpack10pImg(): no input image given.");
256  return;
257  }
258 
259  if (!out) {
260  out.reset(new sensor_msgs::Image);
261  ROS_INFO("camera_aravis::unpack10pImg(): no output image given. Reserved a new one.");
262  }
263 
264  out->header = in->header;
265  out->height = in->height;
266  out->width = in->width;
267  out->is_bigendian = in->is_bigendian;
268  out->step = (4*in->step)/3;
269  out->data.resize((4*in->data.size())/3);
270 
271  // change pixel bit alignment from every 2*10+4 = 24 Bit = 3 Byte format
272  // byte 2 | byte 1 | byte 0
273  // BBBBBBBB 00BB00AA AAAAAAAA
274  // into 2*16 = 32 Bit = 4 Byte format
275  // bytes 3+2 | bytes 1+0
276  // BBBBBBBB BB000000 AAAAAAAA AA000000
277 
278  // note that in this old style GigE format, byte 1 contains the lsb of B as well as A
279 
280  uint8_t* from = in->data.data();
281  uint8_t* to = out->data.data();
282  // unpack 4 mono pixels per iteration
283  for (size_t i=0; i<in->data.size()/3; ++i) {
284 
285  to[0] = from[1]<<6;
286  to[1] = from[0];
287 
288  to[2] = from[1] & 0b11000000;
289  to[3] = from[2];
290 
291  to+=4;
292  from+=3;
293  }
294  out->encoding = out_format;
295 }
296 
297 void unpack12pImg(sensor_msgs::ImagePtr& in, sensor_msgs::ImagePtr& out, const std::string out_format) {
298  if (!in) {
299  ROS_WARN("camera_aravis::unpack12pImg(): no input image given.");
300  return;
301  }
302 
303  if (!out) {
304  out.reset(new sensor_msgs::Image);
305  ROS_INFO("camera_aravis::unpack12pImg(): no output image given. Reserved a new one.");
306  }
307 
308  out->header = in->header;
309  out->height = in->height;
310  out->width = in->width;
311  out->is_bigendian = in->is_bigendian;
312  out->step = (4*in->step)/3;
313  out->data.resize((4*in->data.size())/3);
314 
315  // change pixel bit alignment from every 2*12 = 24 Bit = 3 Byte format LSB
316  // byte 2 | byte 1 | byte 0
317  // BBBBBBBB BBBBAAAA AAAAAAAA
318  // into 2*16 = 32 Bit = 4 Byte format
319  // bytes 3+2 | bytes 1+0
320  // BBBBBBBB BBBB0000 AAAAAAAA AAAA0000
321 
322  uint8_t* from = in->data.data();
323  uint16_t* to = reinterpret_cast<uint16_t*>(out->data.data());
324  // unpack 2 values per iteration
325  for (size_t i=0; i<in->data.size()/3; ++i) {
326 
327  std::memcpy(to, from, 2);
328  to[0] <<= 4;
329 
330  std::memcpy(&to[1], &from[1], 2);
331  to[1] &= 0b1111111111110000;
332 
333  to+=2;
334  from+=3;
335  }
336  out->encoding = out_format;
337 }
338 
339 void unpack12PackedImg(sensor_msgs::ImagePtr& in, sensor_msgs::ImagePtr& out, const std::string out_format) {
340  if (!in) {
341  ROS_WARN("camera_aravis::unpack12pImg(): no input image given.");
342  return;
343  }
344 
345  if (!out) {
346  out.reset(new sensor_msgs::Image);
347  ROS_INFO("camera_aravis::unpack12pImg(): no output image given. Reserved a new one.");
348  }
349 
350  out->header = in->header;
351  out->height = in->height;
352  out->width = in->width;
353  out->is_bigendian = in->is_bigendian;
354  out->step = (4*in->step)/3;
355  out->data.resize((4*in->data.size())/3);
356 
357  // change pixel bit alignment from every 2*12 = 24 Bit = 3 Byte format
358  // byte 2 | byte 1 | byte 0
359  // BBBBBBBB BBBBAAAA AAAAAAAA
360  // into 2*16 = 32 Bit = 4 Byte format
361  // bytes 3+2 | bytes 1+0
362  // BBBBBBBB BBBB0000 AAAAAAAA AAAA0000
363 
364  // note that in this old style GigE format, byte 1 contains the lsb of B as well as A
365 
366  uint8_t* from = in->data.data();
367  uint8_t* to = out->data.data();
368  // unpack 2 values per iteration
369  for (size_t i=0; i<in->data.size()/3; ++i) {
370 
371  to[0] = from[1]<<4;
372  to[1] = from[0];
373 
374  to[2] = from[1] & 0b11110000;
375  to[3] = from[2];
376 
377  to+=4;
378  from+=3;
379  }
380  out->encoding = out_format;
381 }
382 
383 void unpack565pImg(sensor_msgs::ImagePtr& in, sensor_msgs::ImagePtr& out, const std::string out_format) {
384  if (!in) {
385  ROS_WARN("camera_aravis::unpack565pImg(): no input image given.");
386  return;
387  }
388 
389  if (!out) {
390  out.reset(new sensor_msgs::Image);
391  ROS_INFO("camera_aravis::unpack565pImg(): no output image given. Reserved a new one.");
392  }
393 
394  out->header = in->header;
395  out->height = in->height;
396  out->width = in->width;
397  out->is_bigendian = in->is_bigendian;
398  out->step = (3*in->step)/2;
399  out->data.resize((3*in->data.size())/2);
400 
401  // change pixel bit alignment from every 5+6+5 = 16 Bit = 2 Byte format LSB
402  // byte 1 | byte 0
403  // CCCCCBBB BBBAAAAA
404  // into 3*8 = 24 Bit = 3 Byte format
405  // byte 2 | byte 1 | byte 0
406  // CCCCC000 BBBBBB00 AAAAA000
407 
408  uint8_t* from = in->data.data();
409  uint8_t* to = out->data.data();
410  // unpack a whole RGB pixel per iteration
411  for (size_t i=0; i<in->data.size()/2; ++i) {
412  to[0] = from[0] << 3;
413 
414  to[1] = from[0] >> 3;
415  to[1] |= (from[1]<<5);
416  to[1] &= 0b11111100;
417 
418  to[2] = from[1] & 0b11111000;
419 
420  to+=3;
421  from+=2;
422  }
423  out->encoding = out_format;
424 }
425 
426 } // end namespace camera_aravis
camera_aravis::unpack10PackedMonoImg
void unpack10PackedMonoImg(sensor_msgs::ImagePtr &in, sensor_msgs::ImagePtr &out, const std::string out_format)
Definition: conversion_utils.cpp:274
camera_aravis::unpack10pMonoImg
void unpack10pMonoImg(sensor_msgs::ImagePtr &in, sensor_msgs::ImagePtr &out, const std::string out_format)
Definition: conversion_utils.cpp:224
camera_aravis::unpack10p32Img
void unpack10p32Img(sensor_msgs::ImagePtr &in, sensor_msgs::ImagePtr &out, const std::string out_format)
Definition: conversion_utils.cpp:130
camera_aravis::shift
void shift(uint16_t *data, const size_t length, const size_t digits)
Definition: conversion_utils.cpp:64
ros.h
camera_aravis
Definition: camera_aravis_nodelet.h:81
camera_aravis::unpack10PackedImg
void unpack10PackedImg(sensor_msgs::ImagePtr &in, sensor_msgs::ImagePtr &out, const std::string out_format)
Definition: conversion_utils.cpp:178
camera_aravis::unpack12pImg
void unpack12pImg(sensor_msgs::ImagePtr &in, sensor_msgs::ImagePtr &out, const std::string out_format)
Definition: conversion_utils.cpp:318
camera_aravis::unpack565pImg
void unpack565pImg(sensor_msgs::ImagePtr &in, sensor_msgs::ImagePtr &out, const std::string out_format)
Definition: conversion_utils.cpp:404
camera_aravis::interleaveImg
void interleaveImg(sensor_msgs::ImagePtr &in, sensor_msgs::ImagePtr &out, const size_t n_digits, const std::string out_format)
Definition: conversion_utils.cpp:85
camera_aravis::shiftImg
void shiftImg(sensor_msgs::ImagePtr &in, sensor_msgs::ImagePtr &out, const size_t n_digits, const std::string out_format)
Definition: conversion_utils.cpp:70
ROS_WARN
#define ROS_WARN(...)
conversion_utils.h
length
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
camera_aravis::unpack12PackedImg
void unpack12PackedImg(sensor_msgs::ImagePtr &in, sensor_msgs::ImagePtr &out, const std::string out_format)
Definition: conversion_utils.cpp:360
ROS_INFO
#define ROS_INFO(...)
camera_aravis::renameImg
void renameImg(sensor_msgs::ImagePtr &in, sensor_msgs::ImagePtr &out, const std::string out_format)
Definition: conversion_utils.cpp:52


camera_aravis
Author(s): Boitumelo Ruf, Fraunhofer IOSB , Dominik Kleiser, Fraunhofer IOSB , Dominik A. Klein, Fraunhofer FKIE , Steve Safarik, Straw Lab , Andrew Straw, Straw Lab , Floris van Breugel, van Breugel Lab
autogenerated on Wed Mar 13 2024 02:23:00