PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
PixelCodec.h
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2 Program: Plus
3 Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4 See License.txt for details.
5 =========================================================Plus=header=end*/
6 
7 #ifndef __PixelCodec_h
8 #define __PixelCodec_h
9 
10 #include "PlusConfigure.h"
11 
12 #include <iomanip>
13 
14 // Helper macros for YUY2 conversion (source: http://sundararajana.blogspot.ca/2007/12/yuy2-to-rgb24-conversion.html)
15 #define FIXNUM 16
16 #define FIX(a, b) ((int)((a)*(1<<(b))))
17 #define UNFIX(a, b) ((a+(1<<(b-1)))>>(b))
18 // Approximate 255 by 256
19 #define ICCIRUV(x) (((x)<<8)/224)
20 #define ICCIRY(x) ((((x)-16)<<8)/219)
21 // Clip out-range values
22 #define CLIP(t) (((t)>255)?255:(((t)<0)?0:(t)))
23 #define GET_R_FROM_YUV(y, u, v) UNFIX((FIX(1.0, FIXNUM)*(y) + FIX(1.402, FIXNUM)*(v)), FIXNUM)
24 #define GET_G_FROM_YUV(y, u, v) UNFIX((FIX(1.0, FIXNUM)*(y) + FIX(-0.344, FIXNUM)*(u) + FIX(-0.714, FIXNUM)*(v)), FIXNUM)
25 #define GET_B_FROM_YUV(y, u, v) UNFIX((FIX(1.0, FIXNUM)*(y) + FIX(1.772, FIXNUM)*(u)), FIXNUM)
26 #define GET_Y_FROM_RGB(r, g, b) UNFIX((FIX(0.299, FIXNUM)*(r) + FIX(0.587, FIXNUM)*(g) + FIX(0.114, FIXNUM)*(b)), FIXNUM)
27 #define GET_U_FROM_RGB(r, g, b) UNFIX((FIX(-0.169, FIXNUM)*(r) + FIX(-0.331, FIXNUM)*(g) + FIX(0.500, FIXNUM)*(b)), FIXNUM)
28 #define GET_V_FROM_RGB(r, g, b) UNFIX((FIX(0.500, FIXNUM)*(r) + FIX(-0.419, FIXNUM)*(g) + FIX(-0.081, FIXNUM)*(b)), FIXNUM)
29 
30 // VFW compressed formats are listed at http://www.webartz.com/fourcc/
31 static const long VTK_BI_UYVY = 0x59565955;
32 static const long VTK_BI_YUY2 = 0x32595559;
33 
34 #ifndef BI_RGB
35  #define BI_RGB 0L
36 #endif
37 #ifndef BI_JPEG
38  #define BI_JPEG 4L
39 #endif
40 
47 {
48 public:
50  {
54  };
55 
57  {
64  };
65 
66  //----------------------------------------------------------------------------
67  static bool IsConvertToGraySupported(int inputCompression)
68  {
69  switch (inputCompression)
70  {
71  case VTK_BI_YUY2:
72  return true;
73  case BI_RGB:
74  return true;
75  case BI_JPEG:
76  return true;
77  default:
78  return false;
79  }
80  }
81 
82  //----------------------------------------------------------------------------
83  static bool IsConvertToGraySupported(PixelEncoding inputCompression)
84  {
85  switch (inputCompression)
86  {
88  return true;
90  return true;
92  return true;
93  case PixelEncoding_YUY2:
94  return true;
95  case PixelEncoding_MJPG:
96  return true;
97  default:
98  return false;
99  }
100  }
101 
102  //----------------------------------------------------------------------------
103  static std::string GetCompressionModeAsString(int inputCompression)
104  {
105  std::stringstream ss;
106  ss << "0x" << std::hex << std::setw(8) << std::setfill('0') << inputCompression;
107  std::string fourcc = "????";
108  for (int i = 0; i < 4; i++)
109  {
110  fourcc[i] = (unsigned char)(inputCompression >> (8 * i)) & 0xff;
111  if (!isprint(fourcc[i]))
112  {
113  fourcc[i] = '?';
114  }
115  }
116  return fourcc + "(" + std::string(ss.str().c_str()) + ")";
117  }
118 
119  //----------------------------------------------------------------------------
120  static std::string GetCompressionModeAsString(PixelEncoding inputCompression)
121  {
122  switch (inputCompression)
123  {
124  case PixelEncoding_RGB24:
125  return "RGB24";
126  break;
127  case PixelEncoding_BGR24:
128  return "BGR24";
129  break;
131  return "RGBA32";
132  break;
133  case PixelEncoding_YUY2:
134  return "YUY2";
135  break;
136  case PixelEncoding_MJPG:
137  return "MJPG";
138  break;
139  default:
140  LOG_ERROR("Unknown pixel format.");
141  return "Unknown";
142  }
143  }
144 
145  //----------------------------------------------------------------------------
146  static inline PlusStatus ConvertToGray(int inputCompression, int width, int height, unsigned char* s, unsigned char* d)
147  {
148  switch (inputCompression)
149  {
150  case BI_RGB:
151  // decode the grabbed image to the requested output image type
152  RGB24ToGray(width, height, s, d);
153  break;
154  case VTK_BI_YUY2:
155  // decode the grabbed image to the requested output image type
156  YUV422pToGray(width, height, s, d);
157  break;
158  case BI_JPEG:
159  // TODO
160  break;
161  default:
162  LOG_ERROR("Unknown compression type: " << inputCompression);
163  return PLUS_FAIL;
164  }
165  return PLUS_SUCCESS;
166  }
167 
168  //----------------------------------------------------------------------------
169  static inline PlusStatus ConvertToGray(PixelEncoding inputCompression, int width, int height, unsigned char* s, unsigned char* d)
170  {
171  switch (inputCompression)
172  {
173  case PixelEncoding_RGB24:
174  case PixelEncoding_BGR24:
175  // decode the grabbed image to the requested output image type
176  RGB24ToGray(width, height, s, d);
177  break;
179  // decode the grabbed image to the requested output image type
180  RGBA32ToGray(width, height, s, d);
181  break;
182  case PixelEncoding_YUY2:
183  // decode the grabbed image to the requested output image type
184  YUV422pToGray(width, height, s, d);
185  break;
186  case PixelEncoding_MJPG:
187  LOG_ERROR("MJPG to grayscale conversion is not yet supported");
188  break;
189  default:
190  LOG_ERROR("Unknown compression type: " << inputCompression);
191  return PLUS_FAIL;
192  }
193  return PLUS_SUCCESS;
194  }
195 
196  //----------------------------------------------------------------------------
197  static inline PlusStatus ConvertToBGR24(ComponentOrdering outputOrdering, PixelEncoding inputCompression, int width, int height, unsigned char* s, unsigned char* d)
198  {
199  switch (inputCompression)
200  {
201  case PixelEncoding_RGB24:
202  if (outputOrdering == ComponentOrder_RGB)
203  {
204  // Nothing to do, copy out
205  memcpy(d, s, width * height * 3);
206  }
207  else
208  {
209  RGBToBGR(width, height, s, d);
210  }
211  break;
212  case PixelEncoding_BGR24:
213  if (outputOrdering == ComponentOrder_BGR)
214  {
215  // Nothing to do, copy out
216  memcpy(d, s, width * height * 3);
217  }
218  else
219  {
220  RGBToBGR(width, height, s, d);
221  }
222  break;
224  if (outputOrdering == ComponentOrder_RGBA)
225  {
226  RGBA32ToRGB24(width, height, s, d);
227  }
228  else
229  {
230  RGBA32ToBGR24(width, height, s, d);
231  }
232  break;
233  case PixelEncoding_YUY2:
234  // decode the grabbed image to the requested output image type
235  return YUV422pToRGB24(outputOrdering, width, height, s, d);
236  break;
237  case PixelEncoding_MJPG:
238  return MJPGToRGB24(outputOrdering, width, height, s, d);
239  break;
240  default:
241  LOG_ERROR("Unknown compression type: " << inputCompression);
242  return PLUS_FAIL;
243  }
244  return PLUS_SUCCESS;
245  }
246 
247  //----------------------------------------------------------------------------
248  static inline void RGBToBGR(int width, int height, unsigned char* s, unsigned char* d)
249  {
250  for (int i = 0; i < width * height; i++)
251  {
252  *(d++) = s[2];
253  *(d++) = s[1];
254  *(d++) = s[0];
255  s += 3;
256  }
257  }
258 
259  //----------------------------------------------------------------------------
260  static inline void BGRA32ToRGB24(int width, int height, unsigned char* s, unsigned char* d)
261  {
262  for (int i = 0; i < width * height; i++)
263  {
264  *(d++) = s[2];
265  *(d++) = s[1];
266  *(d++) = s[0];
267  s += 4; // ignore alpha channel
268  }
269  }
270 
271  //----------------------------------------------------------------------------
272  static inline void RGBA32ToBGR24(int width, int height, unsigned char* s, unsigned char* d)
273  {
274  for (int i = 0; i < width * height; i++)
275  {
276  *(d++) = s[2];
277  *(d++) = s[1];
278  *(d++) = s[0];
279  s += 4; // ignore alpha channel
280  }
281  }
282 
283  //----------------------------------------------------------------------------
284  static inline void RGBA32ToRGB24(int width, int height, unsigned char* s, unsigned char* d)
285  {
286  for (int i = 0; i < width * height; i++)
287  {
288  *(d++) = *(s++);
289  *(d++) = *(s++);
290  *(d++) = *(s++);
291  s++; // ignore alpha channel
292  }
293  }
294 
295  //----------------------------------------------------------------------------
301  static inline void RGB24ToGray(int width, int height, unsigned char* s, unsigned char* d)
302  {
303  for (int i = 0; i < width * height; i++)
304  {
305  *d = ((unsigned short)(s[0]) + s[1] + s[2]) / 3;
306  d++;
307  s += 3;
308  }
309  }
310 
311  //----------------------------------------------------------------------------
317  static inline void RGBA32ToGray(int width, int height, unsigned char* s, unsigned char* d)
318  {
319  for (int i = 0; i < width * height; i++)
320  {
321  *d = ((unsigned short)(s[0]) + s[1] + s[2]) / 3;
322  d++;
323  s += 4;
324  }
325  }
326 
327  //----------------------------------------------------------------------------
339  static inline void YUVToRGB_Fast(ComponentOrdering outputOrdering, unsigned char* yuv, unsigned char* rgb)
340  {
341  int Y = (yuv[0] - 16) * 76284;
342  int U = yuv[1] - 128;
343  int V = yuv[2] - 128;
344 
345  int R = Y + 104595 * V ;
346  int G = Y - 53281 * V - 25625 * U;
347  int B = Y + 132252 * U;
348 
349  // round
350  R += 32768;
351  G += 32768;
352  B += 32768;
353 
354  // shift
355  R >>= 16;
356  G >>= 16;
357  B >>= 16;
358 
359  // clamp
360  if (R < 0) { R = 0; }
361  if (G < 0) { G = 0; }
362  if (B < 0) { B = 0; }
363 
364  if (R > 255) { R = 255; };
365  if (G > 255) { G = 255; };
366  if (B > 255) { B = 255; };
367 
368  // output
369  rgb[0] = (outputOrdering == ComponentOrder_BGR ? B : R);
370  rgb[1] = G;
371  rgb[2] = (outputOrdering == ComponentOrder_BGR ? R : B);
372  }
373 
374  //----------------------------------------------------------------------------
375  static PlusStatus MJPGToRGB24(ComponentOrdering outputOrdering, int width, int height, unsigned char* s, unsigned char* d)
376  {
377  LOG_ERROR("MJPEG is not supported yet");
378  return PLUS_FAIL;
379  }
380 
381  //----------------------------------------------------------------------------
387  static PlusStatus YUV422pToRGB24(ComponentOrdering outputOrdering, int width, int height, unsigned char* s, unsigned char* d)
388  {
389  unsigned char* p_dest;
390  unsigned char y1, u, y2, v;
391  int Y1, Y2, U, V;
392  unsigned char r, g, b;
393 
394  p_dest = d;
395 
396  int size = height * (width / 2);
397  unsigned long srcIndex = 0;
398  unsigned long dstIndex = 0;
399 
400  for (int i = 0 ; i < size ; i++)
401  {
402  y1 = s[srcIndex];
403  u = s[srcIndex + 1];
404  y2 = s[srcIndex + 2];
405  v = s[srcIndex + 3];
406 
407  Y1 = ICCIRY(y1);
408  U = ICCIRUV(u - 128);
409  Y2 = ICCIRY(y2);
410  V = ICCIRUV(v - 128);
411 
412  r = CLIP(GET_R_FROM_YUV(Y1, U, V));
413  g = CLIP(GET_G_FROM_YUV(Y1, U, V));
414  b = CLIP(GET_B_FROM_YUV(Y1, U, V));
415 
416  p_dest[dstIndex] = outputOrdering == ComponentOrder_BGR ? b : r;
417  p_dest[dstIndex + 1] = g;
418  p_dest[dstIndex + 2] = outputOrdering == ComponentOrder_BGR ? r : b;
419 
420  dstIndex += 3;
421 
422  r = CLIP(GET_R_FROM_YUV(Y2, U, V));
423  g = CLIP(GET_G_FROM_YUV(Y2, U, V));
424  b = CLIP(GET_B_FROM_YUV(Y2, U, V));
425 
426  p_dest[dstIndex] = outputOrdering == ComponentOrder_BGR ? b : r;
427  p_dest[dstIndex + 1] = g;
428  p_dest[dstIndex + 2] = outputOrdering == ComponentOrder_BGR ? r : b;
429 
430  dstIndex += 3;
431  srcIndex += 4;
432  }
433 
434  return PLUS_SUCCESS;
435  }
436 
437  //----------------------------------------------------------------------------
443  static void YUV422pToGray(int width, int height, unsigned char* s, unsigned char* d)
444  {
445  int i;
446  unsigned char* p_dest;
447  unsigned char y1, u, y2, v;
448  int Y1, Y2, U, V;
449  unsigned char r, g, b;
450 
451  p_dest = d;
452 
453  int size = height * (width / 2);
454  unsigned long srcIndex = 0;
455  unsigned long dstIndex = 0;
456 
457  for (i = 0 ; i < size ; i++)
458  {
459  y1 = s[srcIndex];
460  u = s[srcIndex + 1];
461  y2 = s[srcIndex + 2];
462  v = s[srcIndex + 3];
463 
464  Y1 = ICCIRY(y1);
465  U = ICCIRUV(u - 128);
466  Y2 = ICCIRY(y2);
467  V = ICCIRUV(v - 128);
468 
469  r = CLIP(GET_R_FROM_YUV(Y1, U, V));
470  g = CLIP(GET_G_FROM_YUV(Y1, U, V));
471  b = CLIP(GET_B_FROM_YUV(Y1, U, V));
472 
473  p_dest[dstIndex] = (int(b) + g + r) / 3;
474  dstIndex ++;
475 
476  r = CLIP(GET_R_FROM_YUV(Y2, U, V));
477  g = CLIP(GET_G_FROM_YUV(Y2, U, V));
478  b = CLIP(GET_B_FROM_YUV(Y2, U, V));
479 
480  p_dest[dstIndex] = (int(b) + g + r) / 3;
481 
482  dstIndex ++;
483  srcIndex += 4;
484  }
485  }
486 
487 private:
488  PixelCodec(); // prevent instantiation
489 };
490 
491 
492 #endif //__PixelCodec_h
static const long VTK_BI_YUY2
Definition: PixelCodec.h:32
int int int int y2
Definition: phidget22.h:4262
static void BGRA32ToRGB24(int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:260
static void RGBA32ToRGB24(int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:284
static const long VTK_BI_UYVY
Definition: PixelCodec.h:31
int
Definition: phidget22.h:3069
igsioStatus PlusStatus
Definition: PlusCommon.h:40
Initial rotation matrix R
Definition: algo3.m:24
static PlusStatus ConvertToBGR24(ComponentOrdering outputOrdering, PixelEncoding inputCompression, int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:197
#define BI_RGB
Definition: PixelCodec.h:35
static bool IsConvertToGraySupported(int inputCompression)
Definition: PixelCodec.h:67
for i
#define PLUS_FAIL
Definition: PlusCommon.h:43
static void RGBA32ToGray(int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:317
Initial rotation matrix b
Definition: algo3.m:25
static std::string GetCompressionModeAsString(int inputCompression)
Definition: PixelCodec.h:103
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
static PlusStatus ConvertToGray(PixelEncoding inputCompression, int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:169
static void YUVToRGB_Fast(ComponentOrdering outputOrdering, unsigned char *yuv, unsigned char *rgb)
Definition: PixelCodec.h:339
#define GET_R_FROM_YUV(y, u, v)
Definition: PixelCodec.h:23
static std::string GetCompressionModeAsString(PixelEncoding inputCompression)
Definition: PixelCodec.h:120
#define CLIP(t)
Definition: PixelCodec.h:22
int int y1
Definition: phidget22.h:4262
static void RGB24ToGray(int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:301
PhidgetLCD_Font int * width
Definition: phidget22.h:4275
#define ICCIRUV(x)
Definition: PixelCodec.h:19
#define GET_G_FROM_YUV(y, u, v)
Definition: PixelCodec.h:24
static PlusStatus ConvertToGray(int inputCompression, int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:146
PhidgetLCD_Font int int * height
Definition: phidget22.h:4275
#define GET_B_FROM_YUV(y, u, v)
Definition: PixelCodec.h:25
static void YUV422pToGray(int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:443
static bool IsConvertToGraySupported(PixelEncoding inputCompression)
Definition: PixelCodec.h:83
static void RGBToBGR(int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:248
static PlusStatus MJPGToRGB24(ComponentOrdering outputOrdering, int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:375
static PlusStatus YUV422pToRGB24(ComponentOrdering outputOrdering, int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:387
static void RGBA32ToBGR24(int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:272
A utility class that contains static functions for converting between various pixel encodings.
Definition: PixelCodec.h:46
#define ICCIRY(x)
Definition: PixelCodec.h:20
#define BI_JPEG
Definition: PixelCodec.h:38
Position vectors of rods v
Definition: algo3.m:14