image.cc
Go to the documentation of this file.
1 /*
2  * This file is part of the rc_genicam_api package.
3  *
4  * Copyright (c) 2017 Roboception GmbH
5  * All rights reserved
6  *
7  * Author: Heiko Hirschmueller
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the copyright holder nor the names of its contributors
20  * may be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include "image.h"
37 
38 #include "exception.h"
39 #include "pixel_formats.h"
40 
41 #include <cstring>
42 
43 namespace rcg
44 {
45 
46 Image::Image(const Buffer *buffer, std::uint32_t part)
47 {
48  if (buffer->getImagePresent(part))
49  {
50  timestamp=buffer->getTimestampNS();
51 
52  width=buffer->getWidth(part);
53  height=buffer->getHeight(part);
54  xoffset=buffer->getXOffset(part);
55  yoffset=buffer->getYOffset(part);
56  xpadding=buffer->getXPadding(part);
57  ypadding=buffer->getYPadding();
58  frameid=buffer->getFrameID();
59  pixelformat=buffer->getPixelFormat(part);
60  bigendian=buffer->isBigEndian();
61 
62  const size_t size=buffer->getSize(part);
63 
64  pixel.reset(new uint8_t [size]);
65 
66  memcpy(pixel.get(), reinterpret_cast<uint8_t *>(buffer->getBase(part)), size);
67  }
68  else
69  {
70  throw GenTLException("Image::Image(): Now image available.");
71  }
72 }
73 
74 namespace
75 {
76 
81 inline unsigned char clamp8(int v)
82 {
83  const int v2=v<0 ? 0:v;
84  return static_cast<unsigned char>(v2>255 ? 255:v2);
85 }
86 
87 }
88 
89 void convYCbCr411toRGB(uint8_t rgb[3], const uint8_t *row, int i)
90 {
91  const uint32_t j=static_cast<uint32_t>((i>>2)*6);
92  const uint32_t js=static_cast<uint32_t>(i&0x3);
93 
94  int Y=row[j+js];
95  if (js > 1)
96  {
97  Y=row[j+js+1];
98  }
99 
100  const int Cb=static_cast<int>(row[j+2])-128;
101  const int Cr=static_cast<int>(row[j+5])-128;
102 
103  const int rc=(90*Cr+32)>>6;
104  const int gc=(-22*Cb-46*Cr+32)>>6;
105  const int bc=(113*Cb+32)>>6;
106 
107  rgb[0]=clamp8(Y+rc);
108  rgb[1]=clamp8(Y+gc);
109  rgb[2]=clamp8(Y+bc);
110 }
111 
112 void convYCbCr411toQuadRGB(uint8_t rgb[12], const uint8_t *row, int i)
113 {
114  i=(i>>2)*6;
115 
116  const int Y[4]={row[i], row[i+1], row[i+3], row[i+4]};
117  const int Cb=static_cast<int>(row[i+2])-128;
118  const int Cr=static_cast<int>(row[i+5])-128;
119 
120  const int rc=(90*Cr+32)>>6;
121  const int gc=(-22*Cb-46*Cr+32)>>6;
122  const int bc=(113*Cb+32)>>6;
123 
124  for (int j=0; j<4; j++)
125  {
126  *rgb++=clamp8(Y[j]+rc);
127  *rgb++=clamp8(Y[j]+gc);
128  *rgb++=clamp8(Y[j]+bc);
129  }
130 }
131 
132 void getColor(uint8_t rgb[3], const std::shared_ptr<const Image> &img,
133  uint32_t ds, uint32_t i, uint32_t k)
134 {
135  if (ds < 1)
136  ds = 1;
137 
138  i*=ds;
139  k*=ds;
140 
141  if (img->getPixelFormat() == Mono8) // convert from monochrome
142  {
143  size_t lstep=img->getWidth()+img->getXPadding();
144  const uint8_t *p=img->getPixels()+k*lstep+i;
145 
146  uint32_t g=0, n=0;
147 
148  for (uint32_t kk=0; kk<ds; kk++)
149  {
150  for (uint32_t ii=0; ii<ds; ii++)
151  {
152  g+=p[ii];
153  n++;
154  }
155 
156  p+=lstep;
157  }
158 
159  rgb[2]=rgb[1]=rgb[0]=static_cast<uint8_t>(g/n);
160  }
161  else if (img->getPixelFormat() == YCbCr411_8) // convert from YUV
162  {
163  size_t lstep=(img->getWidth()>>2)*6+img->getXPadding();
164  const uint8_t *p=img->getPixels()+k*lstep;
165 
166  uint32_t r=0;
167  uint32_t g=0;
168  uint32_t b=0;
169  uint32_t n=0;
170 
171  for (uint32_t kk=0; kk<ds; kk++)
172  {
173  for (uint32_t ii=0; ii<ds; ii++)
174  {
175  uint8_t v[3];
176  convYCbCr411toRGB(v, p, static_cast<int>(i+ii));
177 
178  r+=v[0];
179  g+=v[1];
180  b+=v[2];
181  n++;
182  }
183 
184  p+=lstep;
185  }
186 
187  rgb[0]=static_cast<uint8_t>(r/n);
188  rgb[1]=static_cast<uint8_t>(g/n);
189  rgb[2]=static_cast<uint8_t>(b/n);
190  }
191 }
192 
193 namespace
194 {
195 
196 /*
197  Convert at green pixel in green-red row.
198 */
199 
200 inline void convertGreenGR(uint8_t &r, uint8_t &g, uint8_t &b,
201  const uint8_t *&row0, const uint8_t *&row1, const uint8_t *&row2)
202 {
203  r=static_cast<uint8_t>((static_cast<int>(*row1)+row1[2]+1)>>1);
204  g=row1[1];
205  b=static_cast<uint8_t>((static_cast<int>(row0[1])+row2[1]+1)>>1);
206 
207  row0++; row1++; row2++;
208 }
209 
210 /*
211  Convert at green pixel in green-blue row.
212 */
213 
214 inline void convertGreenGB(uint8_t &r, uint8_t &g, uint8_t &b,
215  const uint8_t *&row0, const uint8_t *&row1, const uint8_t *&row2)
216 {
217  r=static_cast<uint8_t>((static_cast<int>(row0[1])+row2[1]+1)>>1);
218  g=row1[1];
219  b=static_cast<uint8_t>((static_cast<int>(*row1)+row1[2]+1)>>1);
220 
221  row0++; row1++; row2++;
222 }
223 
224 /*
225  Convert at red pixel.
226 */
227 
228 inline void convertRed(uint8_t &r, uint8_t &g, uint8_t &b,
229  const uint8_t *&row0, const uint8_t *&row1, const uint8_t *&row2)
230 {
231  r=row1[1];
232  g=static_cast<uint8_t>((static_cast<int>(row0[1])+row2[1]+*row1+row1[2]+2)>>2);
233  b=static_cast<uint8_t>((static_cast<int>(*row0)+row0[2]+*row2+row2[2]+2)>>2);
234 
235  row0++; row1++; row2++;
236 }
237 
238 /*
239  Convert at blue pixel.
240 */
241 
242 inline void convertBlue(uint8_t &r, uint8_t &g, uint8_t &b,
243  const uint8_t *&row0, const uint8_t *&row1, const uint8_t *&row2)
244 {
245  r=static_cast<uint8_t>((static_cast<int>(*row0)+row0[2]+*row2+row2[2]+2)>>2);
246  g=static_cast<uint8_t>((static_cast<int>(row0[1])+row2[1]+*row1+row1[2]+2)>>2);
247  b=row1[1];
248 
249  row0++; row1++; row2++;
250 }
251 
252 /*
253  Convert RGB to monochrome.
254 */
255 
256 inline uint8_t rgb2Grey(uint8_t r, uint8_t g, uint8_t b)
257 {
258  return static_cast<uint8_t>((9798*static_cast<uint32_t>(r)+
259  19234*static_cast<uint32_t>(g)+
260  3736*static_cast<uint32_t>(b))/32768);
261 }
262 
263 inline void storeRGBMono(uint8_t *&rgb_out, uint8_t *&mono_out, uint8_t red, uint8_t green,
264  uint8_t blue)
265 {
266  if (rgb_out)
267  {
268  *rgb_out++ = red;
269  *rgb_out++ = green;
270  *rgb_out++ = blue;
271  }
272 
273  if (mono_out)
274  {
275  *mono_out++ = rgb2Grey(red, green, blue);
276  }
277 }
278 
279 /*
280  Convert green-red image row.
281 */
282 
283 void convertBayerGR(uint8_t *rgb_out, uint8_t *mono_out,
284  const uint8_t *row0, const uint8_t *row1, const uint8_t *row2,
285  bool greenfirst, size_t width)
286 {
287  uint8_t red, green, blue;
288 
289  // convert if first pixel is green
290 
291  size_t i=0;
292 
293  if (greenfirst)
294  {
295  convertGreenGR(red, green, blue, row0, row1, row2);
296  storeRGBMono(rgb_out, mono_out, red, green, blue);
297 
298  i++;
299  }
300 
301  while (i+1 < width)
302  {
303  // convert at red pixel
304 
305  convertRed(red, green, blue, row0, row1, row2);
306  storeRGBMono(rgb_out, mono_out, red, green, blue);
307 
308  // convert at green pixel
309 
310  convertGreenGR(red, green, blue, row0, row1, row2);
311  storeRGBMono(rgb_out, mono_out, red, green, blue);
312 
313  i+=2;
314  }
315 
316  // convert at red pixel
317 
318  if (i < width)
319  {
320  convertRed(red, green, blue, row0, row1, row2);
321  storeRGBMono(rgb_out, mono_out, red, green, blue);
322  }
323 }
324 
325 /*
326  Convert green-blue image row.
327 */
328 
329 void convertBayerGB(uint8_t *rgb_out, uint8_t *mono_out,
330  const uint8_t *row0, const uint8_t *row1, const uint8_t *row2,
331  bool greenfirst, size_t width)
332 {
333  uint8_t red, green, blue;
334 
335  // convert if first pixel is green
336 
337  size_t i=0;
338 
339  if (greenfirst)
340  {
341  convertGreenGB(red, green, blue, row0, row1, row2);
342  storeRGBMono(rgb_out, mono_out, red, green, blue);
343 
344  i++;
345  }
346 
347  while (i+1 < width)
348  {
349  // convert at red pixel
350 
351  convertBlue(red, green, blue, row0, row1, row2);
352  storeRGBMono(rgb_out, mono_out, red, green, blue);
353 
354  // convert at green pixel
355 
356  convertGreenGB(red, green, blue, row0, row1, row2);
357  storeRGBMono(rgb_out, mono_out, red, green, blue);
358 
359  i+=2;
360  }
361 
362  // convert at red pixel
363 
364  if (i < width)
365  {
366  convertBlue(red, green, blue, row0, row1, row2);
367  storeRGBMono(rgb_out, mono_out, red, green, blue);
368  }
369 }
370 
371 }
372 
373 bool convertImage(uint8_t *rgb_out, uint8_t *mono_out, const uint8_t *raw, uint64_t pixelformat,
374  size_t width, size_t height, size_t xpadding)
375 {
376  bool ret=true;
377 
378  switch (pixelformat)
379  {
380  case Mono8:
381  case Confidence8:
382  case Error8:
383  {
384  for (size_t k=0; k<height; k++)
385  {
386  if (rgb_out)
387  {
388  for (size_t i=0; i<width; i++)
389  {
390  uint8_t v=raw[i];
391  *rgb_out++ = v;
392  *rgb_out++ = v;
393  *rgb_out++ = v;
394  }
395  }
396 
397  if (mono_out)
398  {
399  std::memcpy(mono_out, raw, width*sizeof(uint8_t));
400  mono_out+=width;
401  }
402 
403  raw+=width+xpadding;
404  }
405  }
406  break;
407 
408  case YCbCr411_8:
409  {
410  size_t pstep=(width>>2)*6+xpadding;
411  for (size_t k=0; k<height; k++)
412  {
413  for (size_t i=0; i<width; i+=4)
414  {
415  if (rgb_out)
416  {
417  uint8_t rgb[12];
418  convYCbCr411toQuadRGB(rgb, raw, static_cast<int>(i));
419 
420  for (int j=0; j<12; j++)
421  {
422  *rgb_out++ = rgb[j];
423  }
424  }
425 
426  if (mono_out)
427  {
428  *mono_out++ = raw[0];
429  *mono_out++ = raw[1];
430  *mono_out++ = raw[3];
431  *mono_out++ = raw[4];
432  }
433  }
434 
435  raw+=pstep;
436  }
437  }
438  break;
439 
440  case RGB8:
441  {
442  for (size_t k=0; k<height; k++)
443  {
444  if (rgb_out)
445  {
446  std::memcpy(rgb_out, raw, 3*width*sizeof(uint8_t));
447  rgb_out+=3*width;
448  }
449 
450  if (mono_out)
451  {
452  size_t j=0;
453  for (size_t i=0; i<width; i++)
454  {
455  *mono_out++ = rgb2Grey(raw[j], raw[j+1], raw[j+2]);
456  j+=3;
457  }
458  }
459 
460  raw+=3*width+xpadding;
461  }
462  }
463  break;
464 
465  case BayerRG8:
466  case BayerBG8:
467  case BayerGR8:
468  case BayerGB8:
469  {
470  // In every row, every second pixel is green and every other pixel is
471  // either red or blue. This flag specifies if the current row is red or
472  // blue.
473 
474  bool greenfirst=(pixelformat == BayerGR8 || pixelformat == BayerGB8);
475  bool red=(pixelformat == BayerRG8 || pixelformat == BayerGR8);
476 
477  // setup temporary buffer that is 1 pixel larger than the image
478 
479  std::unique_ptr<uint8_t []> buffer(new uint8_t [(width+2)*3]);
480  uint8_t *row[3];
481 
482  row[0]=buffer.get();
483  row[1]=row[0]+width+2;
484  row[2]=row[1]+width+2;
485 
486  // initialize buffer with 2 rows, extended by two pixel to avoid a special
487  // treatment for the image border
488 
489  memcpy(row[1]+1, raw+width+xpadding, width*sizeof(uint8_t));
490  memcpy(row[2]+1, raw, width*sizeof(uint8_t));
491 
492  row[1][0]=row[1][2]; row[1][width+1]=row[1][width-1];
493  row[2][0]=row[2][2]; row[2][width+1]=row[2][width-1];
494 
495  // for all rows
496 
497  for (size_t k=0; k<height; k++)
498  {
499  // store next extended row in buffer
500 
501  if (k+1 < height)
502  {
503  uint8_t *p=row[0];
504  row[0]=row[1];
505  row[1]=row[2];
506  row[2]=p;
507 
508  memcpy(row[2]+1, raw+(k+1)*(width+xpadding), width*sizeof(uint8_t));
509 
510  row[2][0]=row[2][2]; row[2][width+1]=row[2][width-1];
511  }
512 
513  if (red)
514  {
515  convertBayerGR(rgb_out, mono_out, row[0], row[1], row[2], greenfirst, width);
516 
517  if (rgb_out) rgb_out+=3*width;
518  if (mono_out) mono_out+=width;
519  }
520  else
521  {
522  convertBayerGB(rgb_out, mono_out, row[0], row[1], row[2], greenfirst, width);
523 
524  if (rgb_out) rgb_out+=3*width;
525  if (mono_out) mono_out+=width;
526  }
527 
528  greenfirst=!greenfirst;
529  red=!red;
530  }
531  }
532  break;
533 
534  default:
535  ret=false;
536  break;
537  }
538 
539  return ret;
540 }
541 
542 }
size_t getYPadding() const
Returns vertical padding of the data in the buffer in bytes.
Definition: buffer.cc:418
size_t ypadding
Definition: image.h:101
Definition: PFNC.h:286
Definition: PFNC.h:272
Definition: PFNC.h:280
size_t getXPadding(std::uint32_t part) const
Returns horizontal padding of the data in the buffer in bytes.
Definition: buffer.cc:405
void convYCbCr411toRGB(uint8_t rgb[3], const uint8_t *row, int i)
Conversion of one pixel from YCbCr411 format (6 bytes for four pixels) to RGB.
Definition: image.cc:89
bool bigendian
Definition: image.h:104
size_t getWidth(std::uint32_t part) const
Returns the width of the image in pixel.
Definition: buffer.cc:333
Definition: PFNC.h:298
size_t width
Definition: image.h:96
void convYCbCr411toQuadRGB(uint8_t rgb[12], const uint8_t *row, int i)
Conversion of a group of four pixels from YCbCr411 format (6 bytes for four pixels) to RGB...
Definition: image.cc:112
The buffer class encapsulates a Genicam buffer that is provided by a stream.
Definition: buffer.h:118
void * getBase(std::uint32_t part) const
Returns the base address of the specified part of the multi-part buffer.
Definition: buffer.cc:231
uint64_t getPixelFormat(std::uint32_t part) const
Returns the pixel format of the specified part as defined in the PFNC.
Definition: buffer.cc:480
#define Error8
Definition: pixel_formats.h:46
Definition: PFNC.h:311
bool convertImage(uint8_t *rgb_out, uint8_t *mono_out, const uint8_t *raw, uint64_t pixelformat, size_t width, size_t height, size_t xpadding)
Converts image to RGB and monochrome format.
Definition: image.cc:373
uint64_t timestamp
Definition: image.h:95
size_t xpadding
Definition: image.h:100
Image(const Buffer *buffer, std::uint32_t part)
Copies the image information of the buffer.
Definition: image.cc:46
size_t xoffset
Definition: image.h:98
size_t yoffset
Definition: image.h:99
uint64_t getTimestampNS() const
Returns the acquisition timestamp of the data in this buffer in ns.
Definition: buffer.cc:591
bool isBigEndian() const
Returns if the data is given as big or little endian.
Definition: buffer.cc:562
Definition: buffer.cc:47
bool getImagePresent(std::uint32_t part) const
Returns if a 2D, 3D or confidence image is present in the specified part.
Definition: buffer.cc:433
uint64_t getFrameID() const
Returns the sequentially incremented number of the frame.
Definition: buffer.cc:428
size_t getYOffset(std::uint32_t part) const
Returns the vertical offset of the data in the buffer in lines from the image origin to handle areas ...
Definition: buffer.cc:387
Definition: PFNC.h:292
size_t height
Definition: image.h:97
std::unique_ptr< uint8_t[]> pixel
Definition: image.h:93
size_t getXOffset(std::uint32_t part) const
Returns the horizontal offset of the data in the buffer in pixels from the image origin to handle are...
Definition: buffer.cc:369
size_t getHeight(std::uint32_t part) const
Returns the height of the image in pixel.
Definition: buffer.cc:351
void getColor(uint8_t rgb[3], const std::shared_ptr< const Image > &img, uint32_t ds, uint32_t i, uint32_t k)
Expects an image in Mono8 or YCbCr411_8 format and returns the color as RGB value at the given pixel ...
Definition: image.cc:132
uint64_t frameid
Definition: image.h:102
uint64_t pixelformat
Definition: image.h:103
size_t getSize(std::uint32_t part) const
Returns the size of the specified part of the mult-part buffer.
Definition: buffer.cc:254


rc_genicam_api
Author(s): Heiko Hirschmueller
autogenerated on Wed Mar 17 2021 02:48:40