image_publisher.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 Roboception GmbH
3  * All rights reserved
4  *
5  * Author: Heiko Hirschmueller
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its contributors
18  * may be used to endorse or promote products derived from this software without
19  * specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "image_publisher.h"
35 
36 #include <rc_genicam_api/image.h>
38 
40 
41 #ifdef __SSSE3__
42 #include <tmmintrin.h>
43 #endif
44 
45 namespace rcgccam
46 {
47 
49 { }
50 
52 {
53  pub_ = it.advertise("image_raw", 1);
54 }
55 
57 {
58  return pub_.getNumSubscribers() > 0;
59 }
60 
61 void ImagePublisher::publish(const sensor_msgs::ImagePtr& image)
62 {
63  if (image && pub_.getNumSubscribers() > 0)
64  {
65  pub_.publish(image);
66  }
67 }
68 
69 std::string rosPixelformat(int& bytes_per_pixel, uint64_t pixelformat)
70 {
71  std::string ret;
72 
73  switch (pixelformat)
74  {
75  case Mono8:
77  bytes_per_pixel = 1;
78  break;
79 
80  case Mono16:
82  bytes_per_pixel = 2;
83  break;
84 
85  case BayerBG8:
87  bytes_per_pixel = 1;
88  break;
89 
90  case BayerBG16:
92  bytes_per_pixel = 2;
93  break;
94 
95  case BayerGB8:
97  bytes_per_pixel = 1;
98  break;
99 
100  case BayerGB16:
102  bytes_per_pixel = 2;
103  break;
104 
105  case BayerGR8:
107  bytes_per_pixel = 1;
108  break;
109 
110  case BayerGR16:
112  bytes_per_pixel = 2;
113  break;
114 
115  case BayerRG8:
117  bytes_per_pixel = 1;
118  break;
119 
120  case BayerRG16:
122  bytes_per_pixel = 2;
123  break;
124 
125  case RGB8:
127  bytes_per_pixel = 3;
128  break;
129 
130  case RGB16:
132  bytes_per_pixel = 6;
133  break;
134 
135  case RGBa8:
137  bytes_per_pixel = 4;
138  break;
139 
140  case RGBa16:
142  bytes_per_pixel = 8;
143  break;
144 
145  case BGRa8:
147  bytes_per_pixel = 4;
148  break;
149 
150  case BGRa16:
152  bytes_per_pixel = 8;
153  break;
154 
155  case YUV422_8:
157  bytes_per_pixel = 2;
158  break;
159 
160  default:
161  ret = "";
162  bytes_per_pixel = 0;
163  break;
164  }
165 
166  return ret;
167 }
168 
169 namespace
170 {
171 
172 /*
173  Copies nmemb elements in inverse order. Each element consists of m bytes. The
174  byte order within each element is not inversed.
175 */
176 
177 void copyInverse(uint8_t *tp, const uint8_t *sp, size_t nmemb, size_t m)
178 {
179  if (m == 1)
180  {
181  // optimization of special case of inversing bytewise
182 
183  tp += nmemb;
184  size_t i=0;
185 
186 #if defined (__SSSE3__)
187  __m128i inv_index=_mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
188 
189  while (i+16 <= nmemb)
190  {
191  tp-=16;
192 
193  __m128i v=_mm_loadu_si128(reinterpret_cast<const __m128i *>(sp));
194  v=_mm_shuffle_epi8(v, inv_index);
195  _mm_storeu_si128(reinterpret_cast<__m128i *>(tp), v);
196 
197  sp+=16;
198  i+=16;
199  }
200 #endif
201 
202  while (i < nmemb)
203  {
204  tp--;
205  *tp = *sp++;
206  i++;
207  }
208  }
209  else
210  {
211  // general case, i.e. m > 1
212 
213  tp += m*nmemb;
214 
215  for (size_t i=0; i<nmemb; i++)
216  {
217  tp -= m;
218 
219  for (size_t k=0; k<m; k++)
220  {
221  tp[k] = *sp++;
222  }
223  }
224  }
225 }
226 
227 }
228 
229 sensor_msgs::ImagePtr rosImageFromBuffer(const std::string& frame_id, const rcg::Buffer* buffer,
230  uint32_t part, bool rotate)
231 {
232  sensor_msgs::ImagePtr im;
233  std::string pixelformat;
234  int bytes_per_pixel;
235 
236  pixelformat = rosPixelformat(bytes_per_pixel, buffer->getPixelFormat(part));
237 
238  // rotation is not supported for all pixel formats
239 
240  if (rotate && pixelformat == sensor_msgs::image_encodings::YUV422)
241  {
242  rotate=false;
243 
244  ROS_WARN_STREAM("Rotation is not supporte for image format: " << pixelformat);
245  }
246 
247  if (pixelformat.size() > 0)
248  {
249  // create image and initialize header
250 
251  im = boost::make_shared<sensor_msgs::Image>();
252  im->encoding = pixelformat;
253 
254  const uint64_t freq = 1000000000ul;
255  uint64_t time = buffer->getTimestampNS();
256 
257  im->header.seq = 0;
258  im->header.stamp.sec = time / freq;
259  im->header.stamp.nsec = time - freq * im->header.stamp.sec;
260  im->header.frame_id = frame_id;
261 
262  // set image size
263 
264  im->width = static_cast<uint32_t>(buffer->getWidth(part));
265  im->height = static_cast<uint32_t>(buffer->getHeight(part));
266  im->is_bigendian = buffer->isBigEndian();
267 
268  // get pointer to image data in buffer
269 
270  const uint8_t* ps = static_cast<const uint8_t*>(buffer->getBase(part));
271  size_t pstep = im->width * bytes_per_pixel + buffer->getXPadding(part);
272 
273  // copy image data
274 
275  im->step = im->width * bytes_per_pixel;
276 
277  im->data.resize(im->step * im->height);
278  uint8_t* pt = reinterpret_cast<uint8_t*>(&im->data[0]);
279 
280  if (im->step != pstep)
281  {
282  if (rotate)
283  {
284  pt += im->step*im->height;
285  for (uint32_t k = 0; k < im->height; k++)
286  {
287  pt -= im->step;
288 
289  copyInverse(pt, ps, im->width, bytes_per_pixel);
290 
291  ps += pstep;
292  }
293  }
294  else
295  {
296  for (uint32_t k = 0; k < im->height; k++)
297  {
298  memcpy(pt, ps, im->step*sizeof(uint8_t));
299 
300  pt += im->step;
301  ps += pstep;
302  }
303  }
304  }
305  else
306  {
307  if (rotate)
308  {
309  copyInverse(pt, ps, im->height*im->width, bytes_per_pixel);
310  }
311  else
312  {
313  memcpy(pt, ps, im->height*im->step*sizeof(uint8_t));
314  }
315  }
316  }
317 
318  return im;
319 }
320 
321 } // namespace rcgccam
BayerGR8
BayerGR8
rcgccam::ImagePublisher::ImagePublisher
ImagePublisher()
Definition: image_publisher.cc:48
pixel_formats.h
sensor_msgs::image_encodings::BAYER_RGGB8
const std::string BAYER_RGGB8
rcg::Buffer::getXPadding
size_t getXPadding(std::uint32_t part) const
image_encodings.h
image_transport::ImageTransport
BayerRG16
BayerRG16
YUV422_8
YUV422_8
rcg::Buffer
BGRa16
BGRa16
rcgccam::rosImageFromBuffer
sensor_msgs::ImagePtr rosImageFromBuffer(const std::string &frame_id, const rcg::Buffer *buffer, uint32_t part, bool rotate)
Converts a (supported) image in a GenICam buffer into a ROS image.
Definition: image_publisher.cc:229
image_transport::Publisher::getNumSubscribers
uint32_t getNumSubscribers() const
BGRa8
BGRa8
sensor_msgs::image_encodings::RGBA8
const std::string RGBA8
sensor_msgs::image_encodings::BAYER_GBRG8
const std::string BAYER_GBRG8
rcg::Buffer::getTimestampNS
uint64_t getTimestampNS() const
rcg::Buffer::getBase
void * getBase(std::uint32_t part) const
sensor_msgs::image_encodings::RGB8
const std::string RGB8
image_transport::ImageTransport::advertise
Publisher advertise(const std::string &base_topic, uint32_t queue_size, bool latch=false)
rcg::Buffer::getHeight
size_t getHeight(std::uint32_t part) const
rcgccam
Definition: camerainfolist.cc:40
rcgccam::ImagePublisher::init
void init(image_transport::ImageTransport &id)
Initialization of publisher.
Definition: image_publisher.cc:51
rcgccam::ImagePublisher::publish
void publish(const sensor_msgs::ImagePtr &image)
Definition: image_publisher.cc:61
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
image.h
RGBa16
RGBa16
BayerGB16
BayerGB16
sensor_msgs::image_encodings::BAYER_BGGR8
const std::string BAYER_BGGR8
BayerRG8
BayerRG8
rcg::Buffer::getPixelFormat
uint64_t getPixelFormat(std::uint32_t part) const
RGB16
RGB16
BayerBG16
BayerBG16
rcg::Buffer::isBigEndian
bool isBigEndian() const
sensor_msgs::image_encodings::YUV422
const std::string YUV422
image_transport::Publisher::publish
void publish(const sensor_msgs::Image &message) const
sensor_msgs::image_encodings::BAYER_BGGR16
const std::string BAYER_BGGR16
sensor_msgs::image_encodings::BGRA16
const std::string BGRA16
sensor_msgs::image_encodings::BAYER_GBRG16
const std::string BAYER_GBRG16
Mono16
Mono16
BayerGR16
BayerGR16
image_publisher.h
rcgccam::ImagePublisher::pub_
image_transport::Publisher pub_
Definition: image_publisher.h:67
RGB8
RGB8
sensor_msgs::image_encodings::RGBA16
const std::string RGBA16
sensor_msgs::image_encodings::BGRA8
const std::string BGRA8
rcgccam::ImagePublisher::used
bool used()
Definition: image_publisher.cc:56
sensor_msgs::image_encodings::MONO8
const std::string MONO8
sensor_msgs::image_encodings::MONO16
const std::string MONO16
RGBa8
RGBa8
rcg::Buffer::getWidth
size_t getWidth(std::uint32_t part) const
sensor_msgs::image_encodings::BAYER_GRBG8
const std::string BAYER_GRBG8
rcgccam::rosPixelformat
std::string rosPixelformat(int &bytes_per_pixel, uint64_t pixelformat)
Translates pixel format from GenICam to ROS.
Definition: image_publisher.cc:69
sensor_msgs::image_encodings::BAYER_GRBG16
const std::string BAYER_GRBG16
BayerBG8
BayerBG8
BayerGB8
BayerGB8
Mono8
Mono8
sensor_msgs::image_encodings::RGB16
const std::string RGB16
sensor_msgs::image_encodings::BAYER_RGGB16
const std::string BAYER_RGGB16


rc_genicam_camera
Author(s): Heiko Hirschmueller
autogenerated on Wed Mar 2 2022 00:49:18