Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ImageConvert.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5 Multimediale Systeme der Informationsverarbeitung
6 Institut fuer Informatik
7 Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 #include "ImageConvert.hh"
26 
27 #include <iostream>
28 #include <Base/Debug/DebugSimple.hh>
29 #include "ToPlanar.cpp"
30 #include "ToInterleaved.cpp"
31 #include "ToHSV.cpp"
32 #include "ToHSL.cpp"
33 
34 using namespace std;
35 using namespace BIAS;
36 
37 #ifdef BIAS_HAVE_IMAGEMAGICKLIB
38  // binding local namespace scope
39  using namespace Magick;
40  using namespace MagickLib;
41  //replace old ImageMagick-namespace with new one
42  #ifdef BIAS_IMAGEMAGICKLIB_V2
43  # define MagickLib MagickCore
44  #endif //BIAS_IMAGEMAGICKLIB_V2
45 #endif
46 
47 #ifdef BIAS_HAVE_DV
48 dv_decoder_t *ImageConvert::DVDecoder_ = NULL;
49 #endif
50 
51 /// one of the elemenatry switch case statements
52 #define SWIC(biasTypeEnum, cpptype, callfunc, src, dst) \
53 case ImageBase::biasTypeEnum :\
54 {\
55  Image< cpptype > typedImg, destImg;\
56  const ImageBase* psrc = &src; \
57  typedImg.StealImage(*const_cast<ImageBase*>(psrc)); \
58  callfunc(typedImg, destImg);\
59  const_cast<ImageBase*>(psrc)->StealImage(typedImg); \
60  dst.StealImage(destImg);\
61 }\
62  break;
63 
64 
65 
66 // use only those case whose instances are compiled
67 // create one macro for each type, use dby CALLFUNC macro
68 // @author Jan Woetzel 05/2006
69 
70 // always compiled
71 #define CASE_UCHAR(func, src, dst) SWIC(ST_unsignedchar, unsigned char, func, src, dst)
72 #define CASE_FLOAT(func, src, dst) SWIC(ST_float, float, func, src, dst)
73 
74 // compiled iff option enabled vias bias_config.h
75 #ifdef BUILD_IMAGE_CHAR
76 # define CASE_CHAR(func, src, dst) SWIC(ST_char, char, func, src, dst)
77 #else
78 # define CASE_CHAR(func, src, dst)
79 #endif
80 
81 #ifdef BUILD_IMAGE_SHORT
82 # define CASE_SHORT(func, src, dst) SWIC(ST_shortint, short int, func, src, dst)
83 #else
84 # define CASE_SHORT(func, src, dst)
85 #endif
86 
87 #ifdef BUILD_IMAGE_USHORT
88 # define CASE_USHORT(func, src, dst) SWIC(ST_unsignedshortint, unsigned short int, func, src, dst)
89 #else
90 # define CASE_USHORT(func, src, dst)
91 #endif
92 
93 #ifdef BUILD_IMAGE_INT
94 # define CASE_INT(func, src, dst) SWIC(ST_int, int, func, src, dst)
95 #else
96 # define CASE_INT(func, src, dst)
97 #endif
98 
99 #ifdef BUILD_IMAGE_UINT
100 # define CASE_UINT(func, src, dst) SWIC(ST_unsignedint, unsigned int, func, src, dst)
101 #else
102 # define CASE_UINT(func, src, dst)
103 #endif
104 
105 #ifdef BUILD_IMAGE_DOUBLE
106 # define CASE_DOUBLE(func, src, dst) SWIC(ST_double, double, func, src, dst)
107 #else
108 # define CASE_DOUBLE(func, src, dst)
109 #endif
110 
111 
112 
113 ///
114 /// creates all switch cases given a function
115 /// no pretty implementation but backward compatible to old macro JW
116 #define CALLFUNC(afunc,source,dest) \
117  CASE_UCHAR (afunc,source,dest) \
118  CASE_FLOAT (afunc,source,dest) \
119  CASE_CHAR (afunc,source,dest) \
120  CASE_SHORT (afunc,source,dest) \
121  CASE_USHORT(afunc,source,dest) \
122  CASE_INT (afunc,source,dest) \
123  CASE_UINT (afunc,source,dest) \
124  CASE_DOUBLE(afunc,source,dest)
125 
126 //
127 // end of macros
128 //
129 
130 
131 // ----- implementation -----
132 
133 int ImageConvert::Convert(ImageBase &source, ImageBase &dest,
134  enum ImageBase::EColorModel targetColorModel,
135  bool bPlanar)
136 {
137  if ( (dest.GetStorageType()!=ImageBase::ST_invalid) &&
138  (dest.GetStorageType()!=source.GetStorageType()) ) {
139  BIASERR("color model conversion cannot convert image from StorageType "
140  <<source.GetStorageType()<<" to an image with StorageType "
141  <<dest.GetStorageType());
142  return -1;
143  }
144 
145  if (source==dest) { ///////////// call the In-Place function
146  if (source.GetColorModel()!=targetColorModel)
147  switch (targetColorModel)
148  {
149  case ImageBase::CM_Grey:
150  switch (source.GetStorageType())
151  {
152  //CALLFUNC_IP(IP_ToGrey,source);
153  // >> start of former CALLFUNC_IP jw
154  case ImageBase::ST_unsignedchar:
155  {
156  Image<unsigned char> ucImg;
157  ucImg.StealImage(source);
158  IP_ToGrey(ucImg);
159  source.StealImage(ucImg);
160  }
161  break;
162  case ImageBase::ST_float:
163  {
164  Image<float> fImg;
165  fImg.StealImage(source);
166  IP_ToGrey(fImg);
167  source.StealImage(fImg);
168  }
169  break;
170 #ifdef BUILD_IMAGE_CHAR
171  case ImageBase::ST_char:
172  {
173  Image<char> cImg;
174  cImg.StealImage(source);
175  IP_ToGrey(cImg);
176  source.StealImage(cImg);
177  }
178  break;
179 #endif // BUILD_IMAGE_CHAR
180 #ifdef BUILD_IMAGE_SHORT
181  case ImageBase::ST_shortint:
182  {
183  Image<short int> sImg;
184  sImg.StealImage(source);
185  IP_ToGrey(sImg);
186  source.StealImage(sImg);
187  }
188  break;
189 #endif // BUILD_IMAGE_SHORT
190 #ifdef BUILD_IMAGE_USHORT
191  case ImageBase::ST_unsignedshortint:
192  {
194  usImg.StealImage(source);
195  IP_ToGrey(usImg);
196  source.StealImage(usImg);
197  }
198  break;
199 #endif // BUILD_IMAGE_USHORT
200 #ifdef BUILD_IMAGE_INT
201  case ImageBase::ST_int:
202  {
203  Image<int> iImg;
204  iImg.StealImage(source);
205  IP_ToGrey(iImg);
206  source.StealImage(iImg);
207  }
208  break;
209 #endif // BUILD_IMAGE_INT
210 #ifdef BUILD_IMAGE_UINT
211  case ImageBase::ST_unsignedint:
212  {
213  Image<unsigned int> uiImg;
214  uiImg.StealImage(source);
215  IP_ToGrey(uiImg);
216  source.StealImage(uiImg);
217  }
218  break;
219 #endif // BUILD_IMAGE_UINT
220 #ifdef BUILD_IMAGE_DOUBLE
221  case ImageBase::ST_double:
222  {
223  Image<double> dImg;
224  dImg.StealImage(source);
225  IP_ToGrey(dImg);
226  source.StealImage(dImg);
227  }
228  break;
229 #endif // BUILD_IMAGE_DOUBLE
230  // << end of former CALLFUNC_IP jw
231 
232  default:
233  BIASERR("invalid storage type in source image");
234  return -2;
235  }
236  break;
237  default:
238  BIASERR("no In-Place-conversion for sourceColorModel:"<<
239  source.GetColorModel()<<
240  " to targetColorModel:"<<targetColorModel<< endl<<
241  "can only In-Place-convert to CM_Grey");
242  return -3;
243  }
244 
245  if (source.IsPlanar() != bPlanar) {
246  ImageBase destImgBase;
247  if (source.IsPlanar()) {
248  switch (source.GetStorageType()) {
249  CALLFUNC(ToInterleaved,source,destImgBase);
250  default:
251  BIASERR("invalid storage type in source image");
252  return -2;
253  }
254  } else { // it is interleaved
255  switch (source.GetStorageType()) {
256  CALLFUNC(ToPlanar,source,destImgBase);
257  default:
258  BIASERR("invalid storage type in source image");
259  return -2;
260  }
261  }
262  source.StealImage(destImgBase);
263  }
264 
265  } else { ///////////////////////// not In-Place
266 
267  switch (targetColorModel)
268  {
269  case ImageBase::CM_Grey:
270  switch (source.GetStorageType())
271  {
272  CALLFUNC(ToGrey,source,dest);
273  default:
274  BIASERR("invalid storage type in source image");
275  return -2;
276  }
277  break;
278  case ImageBase::CM_RGB:
279  switch (source.GetStorageType())
280  {
281  CALLFUNC(ToRGB,source,dest);
282  default:
283  BIASERR("invalid storage type in source image");
284  return -2;
285  }
286  break;
287  case ImageBase::CM_RGBA:
288  switch (source.GetStorageType())
289  {
290  CALLFUNC(ToRGBA,source,dest);
291  default:
292  BIASERR("invalid storage type in source image");
293  return -2;
294  }
295  break;
296  case ImageBase::CM_HSV:
297  switch (source.GetStorageType())
298  {
299  CALLFUNC(ToHSV,source,dest);
300  default:
301  BIASERR("invalid storage type in source image");
302  return -2;
303  }
304  break;
305  case ImageBase::CM_HSL:
306  switch (source.GetStorageType())
307  {
308  CALLFUNC(ToHSL,source,dest);
309  default:
310  BIASERR("invalid storage type in source image");
311  return -2;
312  }
313  break;
314  case ImageBase::CM_hsL:
315  switch (source.GetStorageType())
316  {
317  CALLFUNC(TohsL,source,dest);
318  default:
319  BIASERR("invalid storage type in source image");
320  return -2;
321  }
322  break;
323 
324  default:
325  BIASERR("no conversion available to targetColorModel:"<<
326  targetColorModel);
327  return -3;
328  }
329  }
330  if (source.IsPlanar() != bPlanar) {
331  ImageBase destImgBase;
332  if (source.IsPlanar()) {
333  switch (source.GetStorageType()) {
334  CALLFUNC(ToInterleaved,dest,destImgBase);
335  default:
336  BIASERR("invalid storage type in source image");
337  return -2;
338  }
339  } else { // it is interleaved
340  switch (source.GetStorageType()) {
341  CALLFUNC(ToPlanar,dest,destImgBase);
342  default:
343  BIASERR("invalid storage type in source image");
344  return -2;
345  }
346  }
347  dest.StealImage(destImgBase);
348  }
349  return 0;
350 }
351 
352 /**
353 Sony DFW-X700 :
354 r = y + 1.4022 v got
355 b = y + 1.7710 u
356 g = y - 0.3475 u - 0.7144 v got
357 */
358 #define YUV2RGB(y, u, v, r, g, b)\
359  r = y + ( ((v << 11) + (v << 10) - (v << 8) + (v << 6) - (v << 3) ) >> 11);\
360  g = y - ( ((v<<10) + (v<<9) - (v<<6) - (v<<3) ) >> 11 ) - \
361  ( ((u << 9) + (u << 7) + (u << 6) + (u << 3) + u) >> 11 );\
362  b = y + ( ((u << 12) - (u << 9) + (u << 5)+(u<<4)) >> 11);\
363  r = r < 0 ? 0 : r;\
364  g = g < 0 ? 0 : g;\
365  b = b < 0 ? 0 : b;\
366  r = r > 255 ? 255 : r;\
367  g = g > 255 ? 255 : g;\
368  b = b > 255 ? 255 : b
369 
370 
371 
372 
373 ////////////////////
374 // ToGrey Section //
375 ////////////////////
376 template<class StorageType>
378  Image<StorageType>& dest)
379 {
380  BIASGDOUT(D_CONVERT," ImageConvert::ToGrey()");
381  int res = -1;
382 
383  if ( dest.GetPixelCount() != source.GetPixelCount() ||
384  dest.GetWidth() != source.GetWidth() ||
385  dest.GetHeight() != source.GetHeight() ){
386  BIASGDOUT(D_CONVERT,
387  "ToGrey() should be called with an image of same size");
388  dest.Release();
389  }
390  if ((dest.GetChannelCount() != 1) &&
391  (dest.GetImageData() != source.GetImageData())){
392  BIASGDOUT(D_CONVERT,"ToGrey() should be called with an 1 channel image");
393  dest.Release();
394  }
395 
396  if (dest.IsEmpty()) {
397  dest.Init(source.GetWidth(), source.GetHeight(),1,source.GetStorageType());
398  }
399 
400  switch (source.GetColorModel()) {
401  case ImageBase::CM_Grey:
402  dest = source;
403  res = 0;
404  break;
405  case ImageBase::CM_DV:
406 #ifdef BIAS_HAVE_DV
407  res = DVToRGB_(source,dest);
408  IP_ToGrey(dest);
409 #else
410  BIASERR("CM_DV not supported because BIAS_HAVE_DV not defined!");
411  BIASABORT;
412 #endif
413  break;
414 
415  case ImageBase::CM_RGB:
416  case ImageBase::CM_BGR:
417  res = RGBToGrey_(source,dest);
418  break;
419  case ImageBase::CM_BGRA:
420  res = BGRAToGrey_(source, dest);
421  break;
422  case ImageBase::CM_UYVY422:
423  case ImageBase::CM_YUYV422:
424  res = YUV422ToGrey_(source,dest);
425  break;
426  case ImageBase::CM_YUV420P:
427  res = YUV420PToGrey_(source,dest);
428  break;
429  case ImageBase::CM_YUV411:
430  res = YUV411ToGrey_(source,dest);
431  break;
432  case ImageBase::CM_Bayer_RGGB:
433  case ImageBase::CM_Bayer_GBRG:
434  case ImageBase::CM_Bayer_GRBG:
435  case ImageBase::CM_Bayer_BGGR:
436  // PtGrToGrey_ is not correct
437  res = BayerToGrey_(source,dest);
438  break;
439  case ImageBase::CM_HSL:
440  case ImageBase::CM_hsL:
441  res = HSLToGrey_(source,dest);
442  break;
443  default:
444  BIASERR("ImageConvert::ToGrey(): unknown color model:"<<
445  source.GetColorModel());
446  //BIASBREAK; // do NOT abort, here.
447  return -1;
448  }
449  dest.ChannelCount_=1;
450  dest.WidthStep_=dest.Width_*dest.Depth_;
451  dest.SetColorModel(ImageBase::CM_Grey);
452  // needed for inplace conversion
454  dest.SetROI(*source.GetROI());
455  return res;
456 }
457 
458 
459 template<class StorageType>
460 int BIAS::ImageConvert::GetChannel(Image<StorageType>& image, int channel, bool strip)
461 {
462  BIASGDOUT(D_CONVERT,"GetChannel()");
463  register StorageType *sink = image.GetImageData();
464  register StorageType *src = image.GetImageData();
465 
466  int channelCount = image.GetChannelCount();
467 
468  if (channelCount < channel) {
469  BIASERR("Error: Image has not enough channels.");
470  return -1;
471  }
472 
473  // in place not necessary , as ToRGB() created new dist already
474  if (strip) {
475  for (unsigned long int i = 0; i < image.GetPixelCount(); i++) {
476  sink[0] = src[channel];
477  src +=channelCount;
478  sink++;
479  }
480  image.ChannelCount_= 1;
481  image.WidthStep_ = image.Width_ * image.Depth_ * image.ChannelCount_;
482  image.ImageData_ = realloc(image.ImageData_, sizeof(StorageType)*image.GetPixelCount());
483  image.SetColorModel(ImageBase::CM_Grey);
485  } else {
486  for (unsigned long int i = 0; i < image.GetPixelCount(); i++) {
487  for (int j = 0; j < channelCount; j++) {
488  sink[j] = src[channel];
489  }
490  src += channelCount;
491  sink+= channelCount;
492  }
493  }
494  return 0;
495 }
496 
497 int BIAS::ImageConvert::GetChannel(ImageBase& image, int channel, bool strip)
498 {
499  BIASGDOUT(D_CONVERT,"GetChannel()");
500  register unsigned char *sink = (unsigned char*)image.GetImageData();
501  register unsigned char *src = (unsigned char*)image.GetImageData();
502 
503  int channelCount = image.GetChannelCount();
504 
505  if (channelCount < channel) {
506  BIASERR("Error: Image has not enough channels.");
507  return -1;
508  }
509 
510  int depth = image.GetDepth();
511 
512  if (strip) {
513  for (unsigned long int i = 0; i < image.GetPixelCount(); i++) {
514  for (int k=0; k<depth; k++) {
515  sink[k] = src[channel*depth+k];
516  }
517  src += channelCount*depth;
518  sink+= depth;
519  }
520  image.ChannelCount_=1;
521  image.WidthStep_ = image.Width_ * image.Depth_ * image.ChannelCount_;
522  image.ImageData_ = realloc(image.ImageData_, depth*image.GetPixelCount());
523  image.SetColorModel(ImageBase::CM_Grey);
525  } else {
526  for (unsigned long int i = 0; i < image.GetPixelCount(); i++) {
527  for (int j = 0; j < channelCount; j++) {
528  for (int k=0; k<depth; k++) {
529  sink[j*depth+k] = src[channel*depth+k];
530  }
531  }
532  src += channelCount*depth;
533  sink+= channelCount*depth;
534  }
535  }
536 
537  return 0;
538 }
539 
540 
541 ////////////////////
542 // ToGrey Section //
543 ////////////////////
544 template<class StorageType>
546  Image<StorageType>& dest,
547  const unsigned int channel)
548 {
549  BIASASSERT(source.GetStorageType() == dest.GetStorageType());
550 
551  if (dest.GetImageData() == source.GetImageData()){
552  BIASERR("GetChannel(src,dst,channel) should not be called with"
553  " the same images. In place does not work, currently.");
554  dest.Release();
555  } else if ((dest.GetWidth() != source.GetWidth() ||
556  dest.GetHeight() != source.GetHeight() ))
557  {
558  BIASWARN("GetChannel(src,dst,channel) should be called"
559  "with an image of same size.\n"
560  "src: "<<source.GetWidth()<<"x"<<source.GetHeight()<<"\n"
561  "dst: "<<dest.GetWidth()<<"x"<<dest.GetHeight() );
562  dest.Release();
563  } else if ((dest.GetChannelCount() != 1)
564  && (dest.GetImageData() != source.GetImageData()) )
565  {
566  BIASWARN("GetChannel(src,dst,channel) should be called "
567  "with a 1 channel dest image but has "
568  <<dest.GetChannelCount()<<" channels" );
569  dest.Release();
570  };
571 
572  if (channel >= source.GetChannelCount()){
573  BIASERR("GetChannel(src,dst,channel) - src doesn't have enough channels");
574  return -1;
575  }
576 
577  if (dest.IsEmpty()) {
578  dest.Init(source.GetWidth(), source.GetHeight(),1,source.GetStorageType());
579  dest.SetColorModel( ImageBase::CM_Grey );
580  }
581 
582  const StorageType *s=source.GetImageData();
583  StorageType *d=dest.GetImageData();
584 
585  if (source.IsPlanar()){
586  s += channel*source.GetWidth()*source.GetHeight(); // start offset
587  // TODO use memcpy instead
588  for (unsigned int i=0; i < dest.GetWidth()*dest.GetHeight(); i++){
589  d[0]=s[0];
590  d++;
591  s++;
592  }
593  } else {
594  // interleaved
595  const int step = source.GetChannelCount(); // in units of StorageType
596  s += channel;
597  for (unsigned int i=0; i < dest.GetWidth()*dest.GetHeight(); i++){
598  *d = *s;
599  d++;
600  s+=step;
601  }
602  }
603 
604  dest.ChannelCount_=1;
605  dest.WidthStep_=dest.Width_*dest.Depth_;
606  dest.SetColorModel(ImageBase::CM_Grey);
607  return 0;
608 }
609 
610 
612  ImageBase& dest)
613 {
614  int res = 0;
615  switch (source.GetStorageType()){
616  case ImageBase::ST_unsignedchar:
617  {
618 // BIASASSERT(dest.GetStorageType() == ImageBase::ST_unsignedchar);
619  Image<unsigned char> s(source);
621  res = ToGrey(s, d);
622  dest.StealImage(d);
623  }
624  break;
625 #ifdef BUILD_IMAGE_USHORT
626  case ImageBase::ST_unsignedshortint:
627  {
628 // BIASASSERT(dest.GetStorageType() == ImageBase::ST_unsignedshortint);
629  Image<unsigned short> s(source);
631  res = ToGrey(s, d);
632  dest.StealImage(d);
633  }
634  break;
635 #endif // BUILD_IMAGE_USHORT
636  case ImageBase::ST_float:
637  {
638 // BIASASSERT(dest.GetStorageType() == ImageBase::ST_float);
639  Image<float> s(source);
640  Image<float> d;
641  res = ToGrey(s, d);
642  dest.StealImage(d);
643  }
644  break;
645  default:
646  BIASERR("unfinished code");
647  BIASABORT;
648  break;
649  }
650  dest.SetROI(*source.GetROI());
651  return res;
652 }
653 
654 template <class StorageType>
656  Image<StorageType>& dest)
657 {
658  BIASGDOUT(D_CONVERT,"ImageConvert::RGBToGrey_()");
659  StorageType *p=dest.GetImageData();
660  const StorageType *r, *g, *b;
661 
662  if (source.IsPlanar()){
663  switch (source.GetColorModel()){
664  case ImageBase::CM_RGB:
665  r=source.GetImageData();
666  g=r+(source.GetWidth()*source.GetHeight());
667  b=r+(2*source.GetWidth()*source.GetHeight());
668  break;
669  case ImageBase::CM_BGR:
670  b=source.GetImageData();
671  g=b+(source.GetWidth()*source.GetHeight());
672  r=b+(2*source.GetWidth()*source.GetHeight());
673  break;
674  default:
675  BIASERR("RGBToGrey_ must be called with RGB or BGR ColorModel_");
676  return -1;
677  }
678  const unsigned num_pix = dest.GetWidth()*dest.GetHeight();
679  // casting using rounding is necessary for integer data types to deal
680  // with compile precision
681  if (numeric_limits<StorageType>::is_integer){
682  for (unsigned int i=0; i < num_pix; i++){
683  // + 0.5 is for rounding
684  p[0]=(StorageType)(0.299*(double)(r[0])+
685  0.587*(double)(g[0])+
686  0.114*(double)(b[0])+0.5);
687  p++; r++; g++; b++;
688  }
689  } else {
690  for (unsigned int i=0; i < num_pix; i++){
691  p[0]=(StorageType)(0.299*(double)(r[0])+
692  0.587*(double)(g[0])+
693  0.114*(double)(b[0]));
694  p++; r++; g++; b++;
695  }
696  }
697  } else {
698  switch (source.GetColorModel()) {
699  case ImageBase::CM_RGB:
700  r=source.GetImageData();
701  g=r+1;
702  b=r+2;
703  break;
704  case ImageBase::CM_BGR:
705  b=source.GetImageData();
706  g=b+1;
707  r=b+2;
708  break;
709  default:
710  BIASERR("RGBToGrey_ must be called with RGB or BGR ColorModel_");
711  return -1;
712  }
713  const unsigned num_pix = dest.GetWidth()*dest.GetHeight();
714  // casting is necessray for integer data types to deal
715  // with compile precision
716  if (numeric_limits<StorageType>::is_integer){
717  for (unsigned int i=0; i < num_pix; i++){
718  // + 0.5 is for rounding
719  p[0]=(StorageType)((0.299*(double)(r[0])+
720  0.587*(double)(g[0])+
721  0.114*(double)(b[0]))+0.5);
722  p++; r+=3; g+=3; b+=3;
723  }
724  } else {
725  for (unsigned int i=0; i < num_pix; i++){
726  p[0]=(StorageType)((0.299*(double)(r[0])+
727  0.587*(double)(g[0])+
728  0.114*(double)(b[0])));
729  p++; r+=3; g+=3; b+=3;
730  }
731  }
732  }
733  return 0;
734 }
735 
736 template<class StorageType>
737 int
739  StorageType>& dest)
740 {
741  BIASGDOUT(D_CONVERT,"ImageConvert::BGRAToGrey_()");
742  StorageType *p = dest.GetImageData();
743  const StorageType *r, *g, *b;
744 
745  if (source.IsPlanar())
746  {
747  if (source.GetColorModel() == ImageBase::CM_BGRA)
748  {
749  b = source.GetImageData();
750  g = b + (source.GetWidth() * source.GetHeight());
751  r = b + (2 * source.GetWidth() * source.GetHeight());
752  }
753  else
754  {
755  BIASERR("RGBToGrey_ must be called with BGRA ColorModel_");
756  return -1;
757  }
758  for (unsigned int i = 0; i < dest.GetWidth() * dest.GetHeight(); i++)
759  {
760  // casting using rint is necessray for integer data types to deal
761  // with compile precision
762  // this is solved by introducing a templated Cast function
763  p[0] = Cast<StorageType> (0.299 * (double) (r[0]) +0.587
764  * (double) (g[0]) +0.114 * (double) (b[0]));
765  p++;
766  r++;
767  g++;
768  b++;
769  }
770  }
771  else
772  {
773  if (source.GetColorModel() == ImageBase::CM_BGRA)
774  {
775  b = source.GetImageData();
776  g = b + 1;
777  r = b + 2;
778  }
779  else
780  {
781  BIASERR("RGBToGrey_ must be called with BGRA ColorModel_");
782  return -1;
783  }
784  for (unsigned int i = 0; i < dest.GetWidth() * dest.GetHeight(); i++)
785  {
786  p[0] = Cast<StorageType> (0.299 * (double) (r[0]) +0.587
787  * (double) (g[0]) +0.114 * (double) (b[0]));
788  //cout << "rgb: "<<(int)r[0]<<" "<<(int)g[0]<<" "<<(int)b[0]<<"\tgrey: "<<(int)p[0]<<endl;
789  p++;
790  r += 4;
791  g += 4;
792  b += 4;
793  }
794  }
795  return 0;
796 }
797 
798 
799 
800 template <class StorageType>
802  Image<StorageType>& dest)
803 {
804 
805  register const StorageType *y = source.GetImageData();
806  StorageType *sink = dest.GetImageData();
807  register StorageType *sinkp;
808  bool IdenticalImages = false;
809  BIASGDOUT(D_CONVERT,"ImageConvert::YUV422ToGrey_()");
810 
811  if (y == sink) {
812  BIASGDOUT(D_MI_CONVGREY,"identical images");
813  IdenticalImages = true;
814  sink = new StorageType[source.GetWidth() * source.GetHeight()];
815  }
816 
817  switch (source.GetColorModel()) {
818  case ImageBase::CM_YUYV422:
819  break;
820  case ImageBase::CM_UYVY422:
821  y++;
822  break;
823  default:
824  BIASERR("ImageConvert::YUV422ToGrey_(): unsupported colormodel");
825  return -1;
826  }
827 
828  if (source.IsPlanar()){
829  memcpy(sink, y, dest.GetPixelCount());
830  } else {
831  sinkp = sink;
832  for (register unsigned long int i=0; i < dest.GetPixelCount(); i++){
833  sinkp[0]=y[0];
834  sinkp++;
835  y+=2;
836  // cerr << i << " " << endl;
837  }
838  }
839 
840  if (IdenticalImages) {
842  dest.ChannelCount_=1;
843  dest.RedirectImageDataPointer(sink);
844  }
845  return 0;
846 }
847 
848 
849 
850 ///////////////////////
851 // IP_ToGrey Section //
852 ///////////////////////
853 template <class StorageType>
855 {
856  int res = -1;
857 
858  BIASGDOUT(D_CONVERT,"ImageConvert::IP_ToGrey_()");
859 
860  // if (sizeof(StorageType) != 1){
861  // BIASERR("IP_ToGrey makes only sense with <char> and <unsigned char> images");
862  // return -1;
863  // }
864 
865  switch (img.GetColorModel()) {
866  case ImageBase::CM_Grey://ImageBase::ImageBase::CM_Grey:
867  BIASERR("already in grey");
868  break;
869  case ImageBase::CM_BGR:
870  res = IP_RGBToGrey_(img);
871  break;
872  case ImageBase::CM_BGRA:
873  res = IP_RGBToGrey_(img);
874  break;
875  case ImageBase::CM_RGB:
876  res = IP_RGBToGrey_(img);
877  break;
878  case ImageBase::CM_YUYV422:
879  case ImageBase::CM_UYVY422:
880  res = IP_YUV422ToGrey_(img);
881  break;
882  default:
883  BIASERR("Image::IP_ToGrey(): unknown color model");
884  res = -1;
885  break;
886  }
887  if (res >=0) {
888  img.ChannelCount_=1;
889  img.WidthStep_ = img.Depth_ * img.Width_;
890  img.SetColorModel(ImageBase::CM_Grey);
892  }
893  return res;
894 }
895 
896 
897 //template<class StorageType>
898 #define acc(x,y) ()
899 int ImageConvert::RGBToXYZ(const ImageBase& source, BIAS::Image<float>& dest,
900  float scale)
901 {
902  unsigned int width = source.GetWidth();
903  unsigned int height = source.GetHeight();
904  unsigned int channels = source.GetChannelCount();
905 
906  if (source.GetColorModel() != ImageBase::CM_RGB)
907  {
908  BIASERR("the source image must be in rgb format: error");
909  return -1;
910  }
911 
912  if (channels != 3)
913  {
914  BIASERR("number of channels dont equal 3: error");
915  return -1;
916  }
917 
918  if (width != dest.GetWidth() || height != dest.GetHeight() || channels
919  != dest.GetChannelCount())
920  {
921  dest.Release();
922  dest.Init(width, height, channels);
923  }
924 
925  dest.SetColorModel(ImageBase::CM_XYZ);
926 
927  float rgbToxyz[3][3] = {
928  { 0.490f, 0.310f, 0.200f },
929  { 0.177f, 0.812f, 0.011f },
930  { 0.000f, 0.010f, 0.990f }
931  };
932 
933  float* channelR = new float[width*height];
934  ImageBase::GetChannel(source, 0, channelR);
935  float* channelG = new float[width*height];
936  ImageBase::GetChannel(source, 1, channelG);
937  float* channelB = new float[width*height];
938  ImageBase::GetChannel(source, 2, channelB);
939 
940  for (unsigned int i = 0; i < height; i++)
941  {
942  for (unsigned int j = 0; j < width; j++)
943  {
944  float s[3] = {
945  channelR[i*width+j]/scale,
946  channelG[i*width+j]/scale,
947  channelB[i*width+j]/scale};
948 
949  dest.SetPixel(s[0] * rgbToxyz[0][0] + s[1] * rgbToxyz[0][1] + s[2]
950  * rgbToxyz[0][2], s[0] * rgbToxyz[1][0] + s[1] * rgbToxyz[1][1]
951  + s[2] * rgbToxyz[1][2], s[0] * rgbToxyz[2][0] + s[1]
952  * rgbToxyz[2][1] + s[2] * rgbToxyz[2][2], j, i);
953  }
954  }
955  delete [] channelR;
956  delete [] channelG;
957  delete [] channelB;
958 
959 
960  return 0;
961 }
962 
963 template<class StorageType>
964 int ImageConvert::XYZToRGB(const BIAS::Image<float>& source, BIAS::Image<StorageType>& dest,
965  float scale)
966 {
967  unsigned int width = source.GetWidth();
968  unsigned int height = source.GetHeight();
969  unsigned int channels = source.GetChannelCount();
970 
971  if (source.GetColorModel() != ImageBase::CM_XYZ)
972  {
973  BIASERR("the source image must be in xyz format: error");
974  return -1;
975  }
976 
977  if (channels != 3)
978  {
979  BIASERR("number of channels must equal 3: error");
980  return -1;
981  }
982 
983  if (width != dest.GetWidth() || height != dest.GetHeight() || channels
984  != dest.GetChannelCount())
985  {
986  dest.Release();
987  dest.Init(width, height, channels);
988  }
989 
990  dest.SetColorModel(ImageBase::CM_RGB);
991 
992  float xyzTorgb[3][3] =
993  {
994  { 2.3649f, -0.8971f, -0.4678f },
995  { -0.5156f, 1.4273f, 0.0883f },
996  { 0.0052f, -0.0144f, 1.0092f } };
997 
998  for (unsigned int i = 0; i < height; i++)
999  {
1000  for (unsigned int j = 0; j < width; j++)
1001  {
1002  float s[3] =
1003  { (float) source.PixelValue(j, i, 0), source.PixelValue(j, i, 1),
1004  source.PixelValue(j, i, 2) };
1005  dest.SetPixel((StorageType) rint((s[0] * xyzTorgb[0][0] + s[1] * xyzTorgb[0][1] + s[2]
1006  * xyzTorgb[0][2])*scale), (StorageType) rint((s[0] * xyzTorgb[1][0] + s[1] * xyzTorgb[1][1]
1007  + s[2] * xyzTorgb[1][2])*scale), (StorageType) rint((s[0] * xyzTorgb[2][0] + s[1]
1008  * xyzTorgb[2][1] + s[2] * xyzTorgb[2][2])*scale), j, i);
1009  }
1010  }
1011 
1012  return 0;
1013 }
1014 
1015 int
1016 ImageConvert::XYZToLUV(const BIAS::Image<float>& source, BIAS::Image<float>& dest)
1017 {
1018 
1019  unsigned int width = source.GetWidth();
1020  unsigned int height = source.GetHeight();
1021  unsigned int channels = source.GetChannelCount();
1022  if (source.GetColorModel() != ImageBase::CM_XYZ)
1023  {
1024  BIASERR("the source image must be in xyz format: error");
1025  return -1;
1026  }
1027 
1028  if (channels != 3)
1029  {
1030  BIASERR("number of channels must equal 3: error");
1031  return -1;
1032  }
1033 
1034  if (width != dest.GetWidth() || height != dest.GetHeight() || channels
1035  != dest.GetChannelCount())
1036  {
1037  dest.Release();
1038  dest.Init(width, height, channels);
1039  }
1040 
1041  dest.SetColorModel(ImageBase::CM_LUV);
1042 
1043  float rgbToxyz[3][3] =
1044  {
1045  { 0.490f, 0.310f, 0.200f },
1046  { 0.177f, 0.812f, 0.011f },
1047  { 0.000f, 0.010f, 0.990f } };
1048 
1049  float Xn, Yn, Zn, Un, Vn;
1050 
1051  Xn = rgbToxyz[0][0] + rgbToxyz[0][1] + rgbToxyz[0][2];
1052  Yn = rgbToxyz[1][0] + rgbToxyz[1][1] + rgbToxyz[1][2];
1053  Zn = rgbToxyz[2][0] + rgbToxyz[2][1] + rgbToxyz[2][2];
1054 
1055  Un = (4.0f * Xn) / (Xn + 15.0f * Yn + 3.0f * Zn);
1056  Vn = (9.0f * Yn) / (Xn + 15.0f * Yn + 3.0f * Zn);
1057 
1058  for (unsigned int i = 0; i < height; i++)
1059  {
1060  for (unsigned int j = 0; j < width; j++)
1061  {
1062  // now transform xyz to luv
1063  float x = source.PixelValue(j, i, 0);
1064  float y = source.PixelValue(j, i, 1);
1065  float z = source.PixelValue(j, i, 2);
1066 
1067  // compute L*
1068  float L = y / Yn;
1069 
1070  if (L > 0.008856)
1071  {
1072  L = 116.0f * pow(L, 1.0f / 3.0f) - 16.0f;
1073  }
1074  else
1075  {
1076  L = 903.3f * L;
1077  }
1078 
1079  // //compute u* and v*
1080  float denominator = x + 15.0f * y + 3.0f * z;
1081  float u_star = 0;
1082  float v_star = 0;
1083  if (denominator != 0)
1084  {
1085  u_star = 13.0f * L * ((4.0f * x / denominator) - Un);
1086  v_star = 13.0f * L * ((9.0f * y / denominator) - Vn);
1087 
1088  }
1089 
1090  dest.SetPixel(L, u_star, v_star, j, i);
1091  }
1092  }
1093 
1094  return 0;
1095 }
1096 
1097 int ImageConvert::XYZToLAB(const BIAS::Image<float>& source, BIAS::Image<float>& dest){
1098  unsigned int width = source.GetWidth();
1099  unsigned int height = source.GetHeight();
1100  unsigned int channels = source.GetChannelCount();
1101  if (source.GetColorModel() != ImageBase::CM_XYZ)
1102  {
1103  BIASERR("the source image must be in xyz format: error");
1104  return -1;
1105  }
1106 
1107  if (channels != 3)
1108  {
1109  BIASERR("number of channels must equal 3: error");
1110  return -1;
1111  }
1112 
1113  if (width != dest.GetWidth() || height != dest.GetHeight() || channels
1114  != dest.GetChannelCount())
1115  {
1116  dest.Release();
1117  dest.Init(width, height, channels);
1118  }
1119 
1120  dest.SetColorModel(ImageBase::CM_LAB);
1121 
1122  float rgbToxyz[3][3] =
1123  {
1124  { 0.490f, 0.310f, 0.200f },
1125  { 0.177f, 0.812f, 0.011f },
1126  { 0.000f, 0.010f, 0.990f } };
1127 
1128  float Xn, Yn, Zn;
1129  Xn = rgbToxyz[0][0] + rgbToxyz[0][1] + rgbToxyz[0][2];
1130  Yn = rgbToxyz[1][0] + rgbToxyz[1][1] + rgbToxyz[1][2];
1131  Zn = rgbToxyz[2][0] + rgbToxyz[2][1] + rgbToxyz[2][2];
1132  float th_root = 1.0f/3.0f;
1133 
1134  for (unsigned int i = 0; i < height; i++)
1135  {
1136  for (unsigned int j = 0; j < width; j++)
1137  {
1138  float x = source.PixelValue(j, i, 0);
1139  float y = source.PixelValue(j, i, 1);
1140  float z = source.PixelValue(j, i, 2);
1141 
1142  float x_scaled, y_scaled, z_scaled, x_root, y_root, z_root;
1143  x_scaled = (x/Xn);
1144  y_scaled = (y/Yn);
1145  z_scaled = (z/Zn);
1146 
1147 
1148  if(x_scaled < 0.008856f){
1149  x_root = (903.296f*x_scaled+16.0f)/116.0f;
1150  }else{
1151  x_root = x_scaled * th_root;
1152  }
1153 
1154  if(y_scaled < 0.008856f){
1155  y_root = (903.296f*y_scaled+16.0f)/116.0f;
1156  }else{
1157  y_root = y_scaled * th_root;
1158  }
1159 
1160  if(z_scaled < 0.008856f){
1161  z_root = (903.296f*z_scaled+16.0f)/116.0f;
1162  }else{
1163  z_root = z_scaled * th_root;
1164  }
1165 
1166  // compute L
1167  float L = 116.0f * y_root - 16.0f;
1168 
1169  float a = 500.0f * (x_root - z_root);
1170 
1171  float b = 200.0f * (y_root - z_root);
1172 
1173  dest.SetPixel(L, a, b, j, i);
1174  }
1175  }
1176 
1177  return 0;
1178 }
1179 
1180 int
1181 ImageConvert::LUVToXYZ(const BIAS::Image<float>& source, BIAS::Image<float>& dest)
1182 {
1183  unsigned int width = source.GetWidth();
1184  unsigned int height = source.GetHeight();
1185  unsigned int channels = source.GetChannelCount();
1186 
1187  if (source.GetColorModel() != ImageBase::CM_LUV)
1188  {
1189  BIASERR("the source image must be in luv format: error");
1190  return -1;
1191  }
1192 
1193  if (channels != 3)
1194  {
1195  BIASERR("number of channels must equal 3: error");
1196  return -1;
1197  }
1198 
1199  if (width != dest.GetWidth() || height != dest.GetHeight() || channels
1200  != dest.GetChannelCount())
1201  {
1202  dest.Release();
1203  dest.Init(width, height, channels);
1204  }
1205 
1206  dest.SetColorModel(ImageBase::CM_XYZ);
1207 
1208  float rgbToxyz[3][3] =
1209  {
1210  { 0.490f, 0.310f, 0.200f },
1211  { 0.177f, 0.812f, 0.011f },
1212  { 0.000f, 0.010f, 0.990f } };
1213 
1214  float Xn, Yn, Zn, Un, Vn;
1215 
1216  Xn = rgbToxyz[0][0] + rgbToxyz[0][1] + rgbToxyz[0][2];
1217  Yn = rgbToxyz[1][0] + rgbToxyz[1][1] + rgbToxyz[1][2];
1218  Zn = rgbToxyz[2][0] + rgbToxyz[2][1] + rgbToxyz[2][2];
1219 
1220  Un = (4.0f * Xn) / (Xn + 15.0f * Yn + 3.0f * Zn);
1221  Vn = (9.0f * Yn) / (Xn + 15.0f * Yn + 3.0f * Zn);
1222 
1223  for (unsigned int i = 0; i < height; i++)
1224  {
1225  for (unsigned int j = 0; j < width; j++)
1226  {
1227  float luv[3];
1228  luv[0] = source.PixelValue(j, i, 0);
1229  luv[1] = source.PixelValue(j, i, 1);
1230  luv[2] = source.PixelValue(j, i, 2);
1231 
1232  //-------------------------------
1233  // transform luv to xyz
1234 
1235  float L = luv[0];
1236  float u_star = luv[1];
1237  float v_star = luv[2];
1238  float x = 0;
1239  float y = 0;
1240  float z = 0;
1241 
1242  if (L > 7.9996248)
1243  {
1244  y = Yn * pow((float) ((L + 16.0) / 116.0), 3);
1245  }
1246  else
1247  {
1248  y = Yn * (L / 903.3f);
1249  }
1250 
1251  if (L > 0)
1252  {
1253  float u = u_star / (13.0f * L) + Un;
1254  float v = v_star / (13.0f * L) + Vn;
1255  z = 3.0f * y / v - 5.0f * y - (3.0f / 4.0f) * u * y / v;
1256  x = 9.0f * y / v - 15.0f * y - 3.0f * z;
1257  }
1258 
1259  dest.SetPixel(x, y, z, j, i);
1260  }
1261  }
1262 
1263  return 0;
1264 }
1265 
1266 //template<class StorageType>
1267 int ImageConvert::RGBToLUV(const BIAS::ImageBase& source,
1268  BIAS::Image<float>& dest, float scale)
1269 {
1270  Image<float> xyz;
1271  int res = RGBToXYZ(source, xyz, scale);
1272  if (res != 0)
1273  return res;
1274  XYZToLUV(xyz, dest);
1275  return res;
1276 
1277  return 0;
1278 }
1279 
1280 //template<class StorageType>
1281 int ImageConvert::RGBToLAB(const BIAS::ImageBase& source,
1282  BIAS::Image<float>& dest, float scale)
1283 {
1284  Image<float> xyz;
1285  int res = RGBToXYZ(source, xyz, scale);
1286  if (res != 0)
1287  return res;
1288  XYZToLAB(xyz, dest);
1289  return res;
1290 
1291  return 0;
1292 }
1293 
1294 
1295 
1296 template<class StorageType>
1297 int ImageConvert::LUVToRGB(const BIAS::Image<float>& source,
1298  BIAS::Image<StorageType>& dest, float scale)
1299 {
1300  Image<float> xyz;
1301  int res = LUVToXYZ(source, xyz);
1302  if (res != 0)
1303  return res;
1304  res = XYZToRGB(xyz, dest, scale);
1305 
1306  return res;
1307 }
1308 
1309 
1310 template <class StorageType>
1312 {
1313  StorageType *p=img.GetImageData();
1314  StorageType *r, *g, *b;
1315  if (img.IsPlanar()){
1316  switch (img.GetColorModel()){
1317  case ImageBase::CM_RGB:
1318  r=img.GetImageData();
1319  g=r+(img.GetWidth()*img.GetHeight());
1320  b=r+(2*img.GetWidth()*img.GetHeight());
1321  break;
1322  case ImageBase::CM_BGR:
1323  b=img.GetImageData();
1324  g=b+(img.GetWidth()*img.GetHeight());
1325  r=b+(2*img.GetWidth()*img.GetHeight());
1326  break;
1327  case ImageBase::CM_BGRA:
1328  b = img.GetImageData();
1329  g = b + (img.GetWidth() * img.GetHeight());
1330  r = b + (2 * img.GetWidth() * img.GetHeight());
1331  break;
1332  default:
1333  BIASERR("IP_RGBToGrey_ must be called with RGB or BGR ColorModel_");
1334  return -1;
1335  }
1336  const unsigned num_pix = img.GetWidth()*img.GetHeight();
1337  // casting using rounding is necessary for integer data types to deal
1338  // with compile precision
1339  if (numeric_limits<StorageType>::is_integer){
1340  for (unsigned int i=0; i < num_pix; i++){
1341  // + 0.5 is for rounding
1342  p[0]=(StorageType)(0.299*(double)(r[0])+
1343  0.587*(double)(g[0])+
1344  0.114*(double)(b[0])+0.5);
1345  p++; r++; g++; b++;
1346  }
1347  } else {
1348  for (unsigned int i=0; i < num_pix; i++){
1349  p[0]=(StorageType)(0.299*(double)(r[0])+
1350  0.587*(double)(g[0])+
1351  0.114*(double)(b[0]));
1352  p++; r++; g++; b++;
1353  }
1354  }
1355  } else {
1356  switch (img.GetColorModel()) {
1357  case ImageBase::CM_RGB:
1358  r=img.GetImageData();
1359  g=r+1;
1360  b=r+2;
1361  break;
1362  case ImageBase::CM_BGR:
1363  b=img.GetImageData();
1364  g=b+1;
1365  r=b+2;
1366  break;
1367  case ImageBase::CM_BGRA:
1368  b = img.GetImageData();
1369  g = b + 1;
1370  r = b + 2;
1371  break;
1372  default:
1373  BIASERR("IP_RGBToGrey_ must be called with RGB or BGR or BGRA ColorModel_");
1374  return -1;
1375  }
1376 
1377  const unsigned num_pix = img.GetWidth()*img.GetHeight();
1378  // casting using rounding is necessary for integer data types to deal
1379  // with compile precision
1380  if (numeric_limits<StorageType>::is_integer){
1381  // + 0.5 is for rounding
1382  for (unsigned int i=0; i < num_pix; i++){
1383  p[0]=(StorageType)(0.299*(double)(r[0])+
1384  0.587*(double)(g[0])+
1385  0.114*(double)(b[0])+0.5);
1386  p++; r+=3; g+=3; b+=3;
1387  }
1388  } else {
1389  for (unsigned int i=0; i < num_pix; i++){
1390  p[0]=(StorageType)(0.299*(double)(r[0])+
1391  0.587*(double)(g[0])+
1392  0.114*(double)(b[0]));
1393  p++; r+=3; g+=3; b+=3;
1394  }
1395  }
1396  }
1397  return 0;
1398 }
1399 
1400 
1402 {
1403  if(source.GetColorModel() != BIAS::ImageBase::CM_RGB)
1404  {
1405  cerr<<"Error in rgb2i3! ColorModel should be CM_RGB"<< "\r\n";
1406  return -1;
1407  }
1408  int
1409  width = source.GetWidth(),
1410  height = source.GetHeight();
1411  int size = width*height;
1412  dest.Init(width, height, 3);
1413  //float* siP = sink.GetImageData();
1414  switch(source.GetStorageType()) {
1415  case ImageBase::ST_float:
1416  ConvertRGBToI1I2I3Worker_<float>(static_cast<const float*>(source.GetImageData()),
1417  dest.GetImageData(), size);
1418  break;
1419  case ImageBase::ST_unsignedchar:
1420  ConvertRGBToI1I2I3Worker_<unsigned char>(static_cast<const unsigned char*>(source.GetImageData()),
1421  dest.GetImageData(), size);
1422  break;
1423  default:
1424  BIASERR("unimplemented case!");
1425  return -1;
1426  break;
1427  }
1428 
1429  return 0;
1430 }
1431 
1432 
1433 template<class sourceType>
1434 void BIAS::ImageConvert::ConvertRGBToI1I2I3Worker_(const sourceType* soP, float* siP, int size)
1435 {
1436  sourceType sR, sG, sB;
1437  for(int i = 0; i < size; i++)
1438  {
1439  sR = *soP;
1440  soP++;
1441  sG = *soP;
1442  soP++;
1443  sB = *soP;
1444  soP++;
1445  // I1
1446  /* intensity = (sR + sG + sB)/3;
1447  *siP = (lastIntensity - intensity + 255)/2;
1448  lastIntensity = intensity;*/
1449  *siP = static_cast<float>(sR + sG + sB)/3.f;
1450  siP++;
1451  // I2 + shift
1452  *siP = static_cast<float>(sR - sB)/2.f;
1453  siP++;
1454  // I3 + shift
1455  *siP = static_cast<float>(2*sG - sR - sB)/4.f;
1456  siP++;
1457  }
1458 }
1459 
1460 
1461 template <class StorageType>
1463 {
1464  StorageType *y;
1465 
1466  BIASGDOUT(D_CONVERT,"ImageConvert::IP_YUV422ToGrey_()");
1467 
1468 
1469  if (img.IsPlanar()){
1470  switch (img.GetColorModel()) {
1471  case ImageBase::CM_YUYV422:
1472  img.ChannelCount_=1;
1473  break;
1474  default:
1475  BIASERR("ImageConvert::IP_YUV422ToGrey_() color model not yet implemented");
1476  break;
1477  }
1478  } else {
1479  StorageType *dest=img.GetImageData();
1480  switch (img.GetColorModel()) {
1481  case ImageBase::CM_YUYV422:
1482  y = img.GetImageData();
1483  break;
1484  case ImageBase::CM_UYVY422:
1485  y = img.GetImageData() + 1;
1486  break;
1487  default:
1488  BIASERR("ImageConvert::IP_YUV422ToGrey_(): unsupported colormodel");
1489  return -1;
1490  }
1491  for (unsigned int i=0; i < img.GetWidth()*img.GetHeight(); i++){
1492  dest[0]=y[0];
1493  dest++;
1494  y+=2;
1495  }
1496  }
1497  return 0;
1498 
1499 }
1500 
1501 ////////////////////
1502 // ToRGBA Section //
1503 ////////////////////
1504 
1505 
1506 template <class StorageType>
1508  Image<StorageType>& dest)
1509 {
1510  // only implmented for interleaved, out-of-place conversion so far
1511 
1512  BIASWARNONCE("inefficient code: -> RGBA conversion");
1513  int res = 0;
1514  Image<StorageType> rgb;
1515  if (source.GetColorModel()!=ImageBase::CM_RGB) {
1516  res = ToRGB(source, rgb);
1517  if (res!=0) return res;
1518  } else {
1519  rgb = source;
1520  }
1521 
1522  BIASASSERT(rgb.IsInterleaved());
1523  // add alphachannel
1524  if (!dest.IsEmpty()) dest.Release();
1525  dest.Init(source.GetWidth(), source.GetHeight(), 4);
1526  dest.SetColorModel(ImageBase::CM_RGBA);
1527 
1528  StorageType *pD = rgb.GetImageData();
1529  StorageType *pDA = dest.GetImageData();
1530  for (unsigned int y = 0; y < dest.GetHeight(); y++) {
1531  for (unsigned int x = 0; x < dest.GetWidth(); x++) {
1532  *pDA++ = *pD++;
1533  *pDA++ = *pD++;
1534  *pDA++ = *pD++;
1535  *pDA++ = 0;
1536  }
1537  }
1538  return res;
1539 }
1540 ////////////////////
1541 // ToRGB Section //
1542 ////////////////////
1543 
1544 
1545 template <class StorageType>
1547  Image<StorageType>& dest)
1548 {
1549  int res = -1;
1550  bool inplace=(source.GetImageData()==dest.GetImageData());
1551  Image<StorageType>* tmpdest;
1552  if (inplace)
1553  tmpdest = new Image<StorageType>;
1554  else
1555  tmpdest = &dest;
1556 
1557 
1558  BIASGDOUT(D_CONVERT,"ImageConvert::ToRGB()");
1559  if (!tmpdest->IsEmpty()) {
1560  if (tmpdest->GetChannelCount() != 3 ||
1561  tmpdest->GetWidth()!=source.GetWidth() ||
1562  tmpdest->GetHeight() != source.GetHeight() ){
1563  tmpdest->Release();
1564  }
1565  }
1566 
1567  if (tmpdest->IsEmpty()) {
1568  if (source.GetColorModel() == ImageBase::CM_DV) {
1569 #ifdef BIAS_HAVE_DV
1570  tmpdest->Init(720,576, 3,source.GetStorageType()); // PAL
1571 #else
1572  BIASERR("BIAS_HAVE_DV not defined!!!");
1573  BIASABORT;
1574 #endif
1575  } else {
1576  tmpdest->Init(source.GetWidth(), source.GetHeight(), 3,
1577  source.GetStorageType());
1578  }
1579  }
1580 
1581  switch (source.GetColorModel()) {
1582  case ImageBase::CM_Grey:
1583  case ImageBase::CM_DepthAndVariance:
1584  case ImageBase::CM_Disparity:
1585  case ImageBase::CM_Depth:
1586  res = GreyToRGB_(source,*tmpdest);
1587  break;
1588  case ImageBase::CM_BGR:
1589  res = BGRToRGB_(source,*tmpdest);
1590  break;
1591  case ImageBase::CM_RGB:
1592  *tmpdest = source;
1593  res = 0;
1594  break;
1595  case ImageBase::CM_HSL:
1596  res = HSLToRGB_(source,*tmpdest);
1597  break;
1598  case ImageBase::CM_UYVY422:
1599  res = YUV422ToRGB_(source,*tmpdest);
1600  break;
1601  case ImageBase::CM_YUYV422:
1602  res = YUV422ToRGB_(source,*tmpdest);
1603  break;
1604  case ImageBase::CM_YUV420P:
1605  res = YUV420PToRGB_(source,*tmpdest);
1606  break;
1607  case ImageBase::CM_HSV:
1608  res = HSVToRGB_(source, *tmpdest);
1609  break;
1610  case ImageBase::CM_DV:
1611 #ifdef BIAS_HAVE_DV
1612  res = DVToRGB_(source,*tmpdest);
1613 #else
1614  BIASERR("BIAS_HAVE_DV not defined!!");
1615  BIASABORT;
1616 #endif
1617  break;
1618  case ImageBase::CM_Bayer_RGGB:
1619  case ImageBase::CM_Bayer_GBRG:
1620  case ImageBase::CM_Bayer_GRBG:
1621  case ImageBase::CM_Bayer_BGGR:
1622  res = BayerToRGB_(source,*tmpdest);
1623  break;
1624  case ImageBase::CM_RGBA:
1625  res = RGBAToRGB_(source,*tmpdest);
1626  break;
1627  case ImageBase::CM_BGRA:
1628  res = BGRAToRGB_(source,*tmpdest);
1629  break;
1630  case ImageBase::CM_PGR_XB3_F7M3_GBRG: // tri-image
1631  {
1632  // workaround template implementation:
1633  Image<unsigned char>* ps_uc =
1634  const_cast<Image<unsigned char>*>
1635  (dynamic_cast< const Image<unsigned char>* >(&source));
1636  Image<unsigned char>* pd_uc =
1637  dynamic_cast< Image<unsigned char>* >(&dest);
1638  if ((ps_uc!=NULL) && (pd_uc!=NULL)){
1639  // use unsigned char special implemetation
1641  res = DeinterleaveHorizontal(*ps_uc, tmp3);
1642  if (res!=0){
1643  BIASERR("could not Deinterleave the 3 Bayer patterns.");
1644  return res;
1645  }
1646  // 3 horizontal Bayer pattern images, now.
1647  // convert from Bayer pattern to interpolated RGB
1648  // BayerToRGB_
1649  res = BIAS::ImageConvert::ToRGB(tmp3, *pd_uc);
1650  if (res!=0){
1651  BIASERR("could not Deinterlace");
1652  return res;
1653  }
1654  } else {
1655  BIASERR("CM_PGR_XB3_F7M3_GBRG implemented only for unsigned char.");
1656  return -1;
1657  }
1658  }
1659  break;
1660 
1661  default:
1662  BIASERR("ImageConvert::ToRGB(): unknown color model:"<<
1663  source.GetColorModel());
1664  break;
1665  }
1666  tmpdest->SetColorModel(ImageBase::CM_RGB);
1667 
1668  if (inplace){
1669  dest = *tmpdest;
1670  delete tmpdest;
1671  }
1672 
1673  return res;
1674 }
1675 
1676 
1677 
1678 template <class StorageType>
1680  Image<StorageType>& dest)
1681 {
1682 
1683  BIASGDOUT(D_CONVERT,"BGRToRGB_()");
1684  StorageType *sink = dest.GetImageData();
1685  const StorageType *src = source.GetImageData();
1686  const unsigned long int pixel_count = dest.GetPixelCount();
1687  // in place
1688  if(src == sink){
1689  StorageType tmp;
1690  for (unsigned long int i=0;i<pixel_count; i++) {
1691  tmp = src[2];
1692  sink[2] = src[0];
1693  sink[0] = tmp;
1694  sink+=3;
1695  src+=3;
1696  }
1697  } else {
1698  for (unsigned long int i=0;i<pixel_count; i++) {
1699  sink[2] = src[0];
1700  sink[1] = src[1];
1701  sink[0] = src[2];
1702  sink+=3;
1703  src+=3;
1704  }
1705  }
1706  return 0;
1707 }
1708 
1709 template <class StorageType>
1711  Image<StorageType>& dest)
1712 {
1713  BIASGDOUT(D_CONVERT,"RGBAToRGB()");
1714  register StorageType *sink = dest.GetImageData();
1715  register const StorageType *src = source.GetImageData();
1716  // in place not necessary , as ToRGB() created new dist already
1717  for (unsigned long int i=0;i<dest.GetPixelCount(); i++) {
1718  sink[0] = src[0];
1719  sink[1] = src[1];
1720  sink[2] = src[2];
1721  sink+=3;
1722  src+=4;
1723  }
1724 
1725  return 0;
1726 }
1727 
1728 
1729 
1730 template <class StorageType>
1732  Image<StorageType>& dest)
1733 {
1734  BIASGDOUT(D_CONVERT,"RGBAToRGB()");
1735  register StorageType *sink = dest.GetImageData();
1736  register const StorageType *src = source.GetImageData();
1737  // in place not necessary , as ToRGB() created new dist already
1738  for (unsigned long int i=0;i<dest.GetPixelCount(); i++) {
1739  sink[2] = src[0];
1740  sink[1] = src[1];
1741  sink[0] = src[2];
1742  sink+=3;
1743  src+=4;
1744  }
1745 
1746  return 0;
1747 }
1748 
1749 
1750 template <class StorageType>
1752  Image<StorageType>& dest)
1753 {
1754 
1755 
1756  BIASGDOUT(D_CONVERT,"YUV422ToRGB_()");
1757  StorageType *sink;
1758  bool IdenticalImages = false;
1759  const StorageType *sourcedata = source.GetImageData();
1760 
1761 
1762  if (dest.GetImageData() == sourcedata) {
1763  IdenticalImages = true;
1764  sink = new StorageType[source.GetWidth() * source.GetHeight() * 3];
1765  }
1766  else
1767  sink = dest.GetImageData();
1768 
1769 
1770 #define FASTYUV
1771 
1772 #ifndef FASTYUV
1773  float y,u = 0.0,v=0.0;
1774  float r,g,b;
1775 
1776  int sinkoffset =0;
1777  int yoffset = 0;
1778  int uvoffset = 1;
1779 
1780 
1781 
1782  if (source.ColorModel_ == ImageBase::CM_UYVY422) {
1783  yoffset = 1;
1784  uvoffset = 0;
1785  }
1786 
1787 
1788  for (int j = 0; j < (source.GetWidth() * source.GetHeight()) ; j++)
1789  {
1790  // y = 1.164 *(float) sourcedata[j*2 + yoffset]-16;
1791  y = (float)sourcedata[j*2 + yoffset];
1792  if ( j%2 == 0){
1793  u= (float)sourcedata[j*2+ uvoffset]- 128;
1794  }
1795  else {
1796  v = (float) sourcedata[j*2+ uvoffset ]- 128;
1797  }
1798 
1799  b = rint(y + 1.77 * u );
1800  g = rint(y - 0.714 * v - 0.345 * u );
1801  r = rint(y + 1.4 * v );
1802  // b = rint(y + 2.018 * v );
1803  // g = rint(y - 0.813 * u - 0.391 * v );
1804  // r = rint(y + 1.596 * u );
1805  r = r >255 ? 255: r;
1806  g = g >255 ? 255: g;
1807  b = b >255 ? 255: b;
1808 
1809  r = r <0 ? 0: r;
1810  g = g <0 ? 0: g;
1811  b = b <0 ? 0: b;
1812 
1813 
1814  sink[sinkoffset++ ] = (unsigned char) r;
1815  sink[sinkoffset++] = (unsigned char) g;
1816  sink[sinkoffset++] = (unsigned char) b;
1817  }
1818 
1819 #else
1820  unsigned int i,j;
1821  register int y0,y1,u,v,r,g,b;
1822  if (source.GetColorModel() == ImageBase::CM_UYVY422) {
1823  for (i = 0, j = 0; i < (source.GetWidth()*source.GetHeight() << 1); i += 4, j += 6) {
1824  u = (unsigned char) sourcedata[i + 0] - 128;
1825  y0 = (unsigned char) sourcedata[i + 1];
1826  v = (unsigned char) sourcedata[i + 2] - 128;
1827  y1 = (unsigned char) sourcedata[i + 3];
1828  YUV2RGB (y0, u, v, r, g, b);
1829  sink[j + 0] = StorageType(r);
1830  sink[j + 1] = StorageType(g);
1831  sink[j + 2] = StorageType(b);
1832  YUV2RGB (y1, u, v, r, g, b);
1833  sink[j + 3] = StorageType(r);
1834  sink[j + 4] = StorageType(g);
1835  sink[j + 5] = StorageType(b);
1836  }
1837 
1838  }
1839  else {
1840  for (i = 0, j = 0; i < (dest.GetWidth()*dest.GetHeight() << 1); i += 4, j += 6) {
1841  u = (unsigned char) sourcedata[i + 1] - 128;
1842  y0 = (unsigned char) sourcedata[i + 0];
1843  v = (unsigned char) sourcedata[i + 3] - 128;
1844  y1 = (unsigned char) sourcedata[i + 2];
1845  YUV2RGB (y0, u, v, r, g, b);
1846  sink[j + 0] = StorageType(r);
1847  sink[j + 1] = StorageType(g);
1848  sink[j + 2] = StorageType(b);
1849  YUV2RGB (y1, u, v, r, g, b);
1850  sink[j + 3] = StorageType(r);
1851  sink[j + 4] = StorageType(g);
1852  sink[j + 5] = StorageType(b);
1853  }
1854  }
1855 #endif
1856  if (IdenticalImages) {
1857  dest.ReleaseImageDataPointer();
1858  dest.ChannelCount_=3;
1859  dest.RedirectImageDataPointer(sink);
1860  }
1861 
1862  return 0;
1863 }
1864 
1865 
1866 template <class StorageType>
1868  Image<StorageType>& dest)
1869 {
1870  BIASGDOUT(D_CONVERT,"GreyToRGB_()");
1871 
1872  register const StorageType* src_start = source.GetImageData();
1873  register const StorageType* src_stop = src_start + dest.GetPixelCount();
1874  register StorageType* pDest = dest.GetImageData();
1875 
1876  for (;src_start < src_stop; src_start++) {
1877  *pDest++ = *src_start;
1878  *pDest++ = *src_start;
1879  *pDest++ = *src_start;
1880  }
1881 
1882  return 0;
1883 }
1884 
1885 #ifdef BIAS_HAVE_DV
1886 template <class StorageType>
1888  Image<StorageType>& dest,
1889  unsigned char quality )
1890 {
1891  BIASERR("DVToRGB_ only makes sense with unsigned char images");
1892  return -1;
1893 }
1894 
1895 
1896 namespace BIAS {
1897 template <>
1898 int ImageConvert::DVToRGB_(const Image<unsigned char>& source,
1899  Image<unsigned char>& dest,
1900  unsigned char quality )
1901 {
1902  BIASGDOUT(D_CONVERT,"DVToRGB_()");
1903 
1904  if (!dest.IsEmpty())
1905  if (dest.GetWidth() != 720 || dest.GetHeight() != 576
1906  || dest.GetChannelCount() != 3)
1907  dest.Release();
1908 
1909 
1910  if (dest.IsEmpty()) dest.Init(720, 576,3);
1911 
1912 
1913  unsigned char *sink = dest.GetImageData();
1914  // 4 ? from avi2pics
1915  unsigned char *pixels[3];
1916  int pitches[3];
1917 
1918  pixels[0] = sink; //target
1919  pixels[1] = NULL;
1920  pixels[2] = NULL;
1921 
1922  pitches[0] = 720 * 3;
1923  pitches[1] = 0;
1924  pitches[2] = 0;
1925  if (DVDecoder_ == NULL) DVDecoder_ = dv_decoder_new(0,0,0);
1926  if (DVDecoder_ == NULL) BIASERR("dv_decoder_new() failed.");
1927  // else cout <<"Got new DVDecoder"<<endl;
1928  // dv_init(0,0);// new style for 0.9.8
1929  switch (quality) {
1930  case 0: DVDecoder_->quality = DV_QUALITY_FASTEST ;
1931  break;
1932  case 1: DVDecoder_->quality = DV_QUALITY_FASTEST | DV_QUALITY_AC_1;
1933  break;
1934  case 2: DVDecoder_->quality = DV_QUALITY_COLOR;
1935  break;
1936  case 3: DVDecoder_->quality = DV_QUALITY_COLOR | DV_QUALITY_AC_1;
1937  break;
1938  case 4: DVDecoder_->quality = DV_QUALITY_BEST;
1939  break;
1940  }
1941  //
1942  // decoder->quality = DV_QUALITY_COLOR | DV_QUALITY_DC;
1943  //decoder->quality = DV_QUALITY_COLOR | DV_QUALITY_AC_1;
1944  // decoder->quality = DV_QUALITY_BEST;
1945 
1946  dv_parse_header(DVDecoder_, source.GetImageData());
1947  dv_decode_full_frame(DVDecoder_, source.GetImageData(),
1948  e_dv_color_rgb, pixels, pitches);
1949 
1950  return 0;
1951 }
1952 
1953 } // namespace BIAS
1954 
1955 #endif // of BIAS_HAVE_DV
1956 
1957 
1958 
1959 
1960 
1961 template <class StorageType>
1963  Image<StorageType>& dest)
1964 {
1965  BIASGDOUT(D_CONVERT," Image::BayerToGreySlow_()");
1966 
1967  StorageType *sink = dest.GetImageData() ;
1968  const StorageType *src = source.GetImageData() ;
1969 
1970 
1971  int Mask[8];
1972  StorageType R=0,G=0,B=0;
1973  unsigned int srcskip;
1974  srcskip = source.GetWidth() ;
1975 
1976  Mask[0] = - (int(source.GetWidth()) +1);
1977  Mask[1] = - int(source.GetWidth());
1978  Mask[2] = - (int(source.GetWidth()) -1);
1979  Mask[3] = -1;
1980  Mask[4] = +1;
1981  Mask[5] = int(source.GetWidth()) -1;
1982  Mask[6] = + int(source.GetWidth());
1983  Mask[7] = int(source.GetWidth()) +1;
1984 
1985  unsigned int xoffset = 0;
1986  unsigned int yoffset = 0;
1987  switch (source.GetColorModel()) {
1988  case ImageBase::CM_Bayer_RGGB:
1989  // first pixel in first line
1990  R = *src;
1991  G = (*(src+srcskip)+*(src+1))/2;
1992  B = *(src+srcskip+1);
1993  break;
1994  case ImageBase::CM_Bayer_GBRG:
1995  yoffset = 1;
1996  // first pixel in first line
1997  G = *src;
1998  R = *(src+srcskip);
1999  B = *(src+1);
2000  break;
2001  case ImageBase::CM_Bayer_GRBG:
2002  xoffset = 1;
2003  // first pixel in first line
2004  G = *src;
2005  B = *(src+srcskip);
2006  R = *(src+1);
2007  break;
2008  case ImageBase::CM_Bayer_BGGR:
2009  xoffset = 1;yoffset = 1;
2010  // first pixel in first line
2011  B = *src;
2012  G = (*(src+srcskip)+*(src+1))/2;
2013  R = *(src+srcskip+1);
2014  break;
2015  default:; }
2016  *sink++ = Cast<StorageType>(0.299*(double)R+0.587*(double)G+0.114*(double)B);
2017  src++;
2018  // first line
2019  if (0 == yoffset) {
2020  for (unsigned int x=1; x<(unsigned int)dest.GetWidth()-1; x++){
2021  if (x%2 == xoffset) { // staying on Red
2022  R = *src;
2023  G = ( *(src+Mask[3])+ *(src+Mask[4]) + *(src+Mask[6]) ) /3;
2024  B = ( *(src+Mask[5]) + *(src+Mask[7])) /2;
2025  }
2026  else { // staying on Green
2027  R = ( *(src+Mask[3]) + *(src+Mask[4]) ) /2;
2028  G = *src;
2029  B = (*(src+Mask[6]) ) ;
2030  }
2031  *sink++ = Cast<StorageType>(0.299*(double)R+
2032  0.587*(double)G+0.114*(double)B);
2033  src++;
2034  }
2035  }
2036  else {
2037  for (unsigned int x=1; x<(unsigned int)dest.GetWidth()-1; x++){
2038  if (x%2 == xoffset) { // staying on Green
2039  R = ( *(src+Mask[6]) ) ;
2040  G = *src;
2041  B = ( *(src+Mask[3]) + *(src+Mask[4]) ) /2;
2042  }
2043  else { // staying on Blue
2044  R = ( *(src+Mask[5]) + *(src+Mask[7])) /2;
2045  G = ( *(src+Mask[3]) + *(src+Mask[4]) + *(src+Mask[6]) ) /3;
2046  B = *src;
2047  }
2048  *sink++ = Cast<StorageType>(0.299*(double)R+0.587*(double)G+0.114*(double)B);
2049  src++;
2050  }
2051  }
2052  // last pixel in first line
2053  if (0 == yoffset) {
2054  if ((dest.GetWidth()-1)%2 == xoffset) { // staying on Red
2055  R = *src;
2056  G = ( *(src+Mask[3])+ *(src+Mask[6]) ) /2;
2057  B = *(src+Mask[5]) ;
2058  }
2059  else { // staying on Green
2060  R = *(src+Mask[3]);
2061  G = *src;
2062  B = (*(src+Mask[6]) ) ;
2063  }
2064  }
2065  else {
2066  if ((dest.GetWidth()-1)%2 == xoffset) { // staying on Green
2067  R = ( *(src+Mask[6]) ) ;
2068  G = *src;
2069  B = *(src+Mask[3]) ;
2070  }
2071  else { // staying on Blue
2072  R = *(src+Mask[5]);
2073  G = ( *(src+Mask[3]) + *(src+Mask[6]) ) /2;
2074  B = *src;
2075  }
2076  }
2077  *sink++ = Cast<StorageType>(0.299*(double)R+0.587*(double)G+0.114*(double)B);
2078  src++;
2079 
2080 
2081  //loop
2082  for (unsigned int y=1; y<(unsigned int)source.GetHeight()-1; y++) {
2083  // first pixel in line
2084  if (y%2 == yoffset)
2085  if (0%2 == xoffset) { // staying on Red
2086  R = *src;
2087  G = (*(src+Mask[1]) + *(src+Mask[4]) + *(src+Mask[6]) ) /3;
2088  B = ( *(src+Mask[2]) + *(src+Mask[7])) /2;
2089  } else { // staying on Green
2090  R = *(src+Mask[4]);
2091  G = *src;
2092  B = ( *(src+Mask[1]) + *(src+Mask[6]) ) /2;
2093  }
2094  else
2095  if (0 == xoffset) { // staying on Green
2096  R = ( *(src+Mask[1]) + *(src+Mask[6]) ) /2;
2097  G = *src;
2098  B = *(src+Mask[4]);
2099  }
2100  else { // staying on Blue
2101  R = ( *(src+Mask[0]) + *(src+Mask[7])) /2;
2102  G = (*(src+Mask[1]) + *(src+Mask[4]) + *(src+Mask[6]) ) /3;
2103  B = *src;
2104  }
2105  *sink++ = Cast<StorageType>(0.299*(double)R+0.587*(double)G+0.114*(double)B);
2106  src++;
2107  // main part of line
2108  for (unsigned int x=1; x<(unsigned int)source.GetWidth()-1; x++) {
2109  if (y%2 == yoffset)
2110  if (x%2 == xoffset) { // staying on Red
2111  R = *src;
2112  G = (*(src+Mask[1]) + *(src+Mask[3])
2113  + *(src+Mask[4]) + *(src+Mask[6]) ) /4;
2114  B = ( *(src+Mask[0]) + *(src+Mask[2])
2115  + *(src+Mask[5]) + *(src+Mask[7])) /4;
2116  } else { // staying on Green
2117  R = ( *(src+Mask[3]) + *(src+Mask[4]) ) /2;
2118  G = *src;
2119  B = ( *(src+Mask[1]) + *(src+Mask[6]) ) /2;
2120  }
2121  else
2122  if (x%2 == xoffset) { // staying on Green
2123  R = ( *(src+Mask[1]) + *(src+Mask[6]) ) /2;
2124  G = *src;
2125  B = ( *(src+Mask[3]) + *(src+Mask[4]) ) /2;
2126  }
2127  else { // staying on Blue
2128  R = ( *(src+Mask[0]) + *(src+Mask[2])
2129  + *(src+Mask[5]) + *(src+Mask[7])) /4;
2130  G = (*(src+Mask[1]) + *(src+Mask[3])
2131  + *(src+Mask[4]) + *(src+Mask[6]) ) /4;
2132  B = *src;
2133  }
2134  *sink++ = Cast<StorageType>(0.299*(double)R+0.587*(double)G+0.114*(double)B);
2135  src++;
2136  }
2137  // last pixel in line
2138  if (y%2 == yoffset)
2139  if ((srcskip-1)%2 == xoffset) { // staying on Red
2140  R = *src;
2141  G = (*(src+Mask[1]) + *(src+Mask[3]) + *(src+Mask[6]) ) /3;
2142  B = ( *(src+Mask[0]) + *(src+Mask[5])) /2;
2143  } else { // staying on Green
2144  R = *(src+Mask[3]) ;
2145  G = *src;
2146  B = ( *(src+Mask[1]) + *(src+Mask[6]) ) /2;
2147  }
2148  else
2149  if ((srcskip-1)%2 == xoffset) { // staying on Green
2150  R = ( *(src+Mask[1]) + *(src+Mask[6]) ) /2;
2151  G = *src;
2152  B = *(src+Mask[3]);
2153  }
2154  else { // staying on Blue
2155  R = ( *(src+Mask[0]) + *(src+Mask[5])) /2;
2156  G = (*(src+Mask[1]) + *(src+Mask[3])+ *(src+Mask[6]) ) /3;
2157  B = *src;
2158  }
2159  *sink++ = Cast<StorageType>(0.299*(double)R+0.587*(double)G+0.114*(double)B);
2160  src++;
2161 
2162 
2163  }
2164  // first pixel in last line
2165  if ((source.GetHeight()-1)%2 == yoffset) {
2166  if (0 == xoffset) { // staying on Red
2167  R = *src;
2168  G = ( *(src+Mask[1])+ *(src+Mask[4]) ) /2;
2169  B = *(src+Mask[2]) ;
2170  }
2171  else { // staying on Green
2172  R = *(src+Mask[4]);
2173  G = *src;
2174  B = (*(src+Mask[1]) ) ;
2175  }
2176  }
2177  else {
2178  if (0 == xoffset) { // staying on Green
2179  R = ( *(src+Mask[1]) ) ;
2180  G = *src;
2181  B = *(src+Mask[4]) ;
2182  }
2183  else { // staying on Blue
2184  R = *(src+Mask[2]);
2185  G = ( *(src+Mask[1]) + *(src+Mask[4]) ) /2;
2186  B = *src;
2187  }
2188  }
2189  *sink++ = Cast<StorageType>(0.299*(double)R+0.587*(double)G+0.114*(double)B);
2190  src++;
2191  // last line
2192  if ((source.GetHeight()-1)%2 == yoffset) {
2193  for (unsigned int x=1; x<(unsigned int)dest.GetWidth()-1; x++){
2194  if (x%2 == xoffset) { // staying on Red
2195  R = *src;
2196  G = ( *(src+Mask[3])+ *(src+Mask[1]) + *(src+Mask[4]) ) /3;
2197  B = ( *(src+Mask[0]) + *(src+Mask[2])) /2;
2198  }
2199  else { // staying on Green
2200  R = ( *(src+Mask[3]) + *(src+Mask[4]) ) /2;
2201  G = *src;
2202  B = (*(src+Mask[1]) ) ;
2203  }
2204  *sink++ = Cast<StorageType>(0.299*(double)R+0.587*(double)G+0.114*(double)B);
2205  src++;
2206  }
2207  }
2208  else {
2209  for (unsigned int x=1; x<(unsigned int)dest.GetWidth()-1; x++){
2210  if (x%2 == xoffset) { // staying on Green
2211  R = ( *(src+Mask[1]) ) ;
2212  G = *src;
2213  B = ( *(src+Mask[3]) + *(src+Mask[4]) ) /2;
2214  }
2215  else { // staying on Blue
2216  R = ( *(src+Mask[0]) + *(src+Mask[2])) /2;
2217  G = ( *(src+Mask[1]) + *(src+Mask[3]) + *(src+Mask[4]) ) /3;
2218  B = *src;
2219  }
2220  *sink++ = Cast<StorageType>(0.299*(double)R+0.587*(double)G+0.114*(double)B);
2221  src++;
2222  }
2223  }
2224  // last pixel in last line
2225  if ((source.GetHeight()-1)%2 == yoffset) {
2226  if ((dest.GetWidth()-1)%2 == xoffset) { // staying on Red
2227  R = *src;
2228  G = ( *(src+Mask[3])+ *(src+Mask[1]) ) /2;
2229  B = *(src+Mask[0]) ;
2230  }
2231  else { // staying on Green
2232  R = *(src+Mask[3]);
2233  G = *src;
2234  B = (*(src+Mask[1]) ) ;
2235  }
2236  }
2237  else {
2238  if ((dest.GetWidth()-1)%2 == xoffset) { // staying on Green
2239  R = ( *(src+Mask[1]) ) ;
2240  G = *src;
2241  B = *(src+Mask[3]) ;
2242  }
2243  else { // staying on Blue
2244  R = *(src+Mask[0]);
2245  G = ( *(src+Mask[3]) + *(src+Mask[1]) ) /2;
2246  B = *src;
2247  }
2248  }
2249  *sink++ = Cast<StorageType>(0.299*(double)R+0.587*(double)G+0.114*(double)B);
2250  src++;
2251  return 0;
2252 }
2253 
2254 
2255 
2256 template <class StorageType>
2258  Image<StorageType>& dest )
2259 {
2260  BIASGDOUT(D_CONVERT," Image::BayerToRGB_()");
2261 
2262  //BayerToRGB(source,dest,BAYER_DEMOSAIC_METHOD_BILINEAR);
2263 
2264  StorageType *sink = dest.GetImageData() ;
2265  const StorageType *src = source.GetImageData() ;
2266 
2267  // BayerToRGBSimple_((unsigned char*)source.GetImageData(),(unsigned char*)dest.GetImageData(),
2268  // source.GetWidth(),source.GetHeight(),source.GetColorModel());
2269 
2270 
2271  //BayerToRGBPGR_(source, dest );
2272 
2273 
2274 
2275  BIASASSERT(sink!=NULL);
2276  BIASASSERT(src!=NULL);
2277 
2278 
2279  int Mask[8];
2280  StorageType R=0,G=0,B=0;
2281  unsigned int srcskip;
2282  srcskip = source.GetWidth() ;
2283 
2284  Mask[0] = - (int(source.GetWidth()) +1);
2285  Mask[1] = - int(source.GetWidth());
2286  Mask[2] = - (int(source.GetWidth()) -1);
2287  Mask[3] = -1;
2288  Mask[4] = +1;
2289  Mask[5] = int(source.GetWidth()) -1;
2290  Mask[6] = + int(source.GetWidth());
2291  Mask[7] = int(source.GetWidth()) +1;
2292 
2293  unsigned int xoffset = 0;
2294  unsigned int yoffset = 0;
2295  switch (source.GetColorModel()) {
2296  case ImageBase::CM_Bayer_RGGB:
2297  // first pixel in first line
2298  R = *src;
2299  G = (*(src+srcskip)+*(src+1))/2;
2300  B = *(src+srcskip+1);
2301  break;
2302  case ImageBase::CM_Bayer_GBRG:
2303  yoffset = 1;
2304  // first pixel in first line
2305  G = *src;
2306  R = *(src+srcskip);
2307  B = *(src+1);
2308  break;
2309  case ImageBase::CM_Bayer_GRBG:
2310  xoffset = 1;
2311  // first pixel in first line
2312  G = *src;
2313  B = *(src+srcskip);
2314  R = *(src+1);
2315  break;
2316  case ImageBase::CM_Bayer_BGGR:
2317  xoffset = 1;yoffset = 1;
2318  // first pixel in first line
2319  B = *src;
2320  G = (*(src+srcskip)+*(src+1))/2;
2321  R = *(src+srcskip+1);
2322  break;
2323  default:; }
2324  sink[0]=R; sink[1]=G; sink[2]=B;
2325  sink+=3; src++;
2326  // first line
2327  if (0 == yoffset) {
2328  for (unsigned int x=1; x<(unsigned int)dest.GetWidth()-1; x++){
2329  if (x%2 == xoffset) { // staying on Red
2330  R = *src;
2331  G = ( *(src+Mask[3])+ *(src+Mask[4]) + *(src+Mask[6]) ) /3;
2332  B = ( *(src+Mask[5]) + *(src+Mask[7])) /2;
2333  }
2334  else { // staying on Green
2335  R = ( *(src+Mask[3]) + *(src+Mask[4]) ) /2;
2336  G = *src;
2337  B = (*(src+Mask[6]) ) ;
2338  }
2339  *sink++ =R;
2340  *sink++ =G;
2341  *sink++ =B;
2342  src++;
2343  }
2344  }
2345  else {
2346  for (unsigned int x=1; x<(unsigned int)dest.GetWidth()-1; x++){
2347  if (x%2 == xoffset) { // staying on Green
2348  R = ( *(src+Mask[6]) ) ;
2349  G = *src;
2350  B = ( *(src+Mask[3]) + *(src+Mask[4]) ) /2;
2351  }
2352  else { // staying on Blue
2353  R = ( *(src+Mask[5]) + *(src+Mask[7])) /2;
2354  G = ( *(src+Mask[3]) + *(src+Mask[4]) + *(src+Mask[6]) ) /3;
2355  B = *src;
2356  }
2357  *sink++ =R;
2358  *sink++ =G;
2359  *sink++ =B;
2360  src++;
2361  }
2362  }
2363  // last pixel in first line
2364  if (0 == yoffset) {
2365  if ((dest.GetWidth()-1)%2 == xoffset) { // staying on Red
2366  R = *src;
2367  G = ( *(src+Mask[3])+ *(src+Mask[6]) ) /2;
2368  B = *(src+Mask[5]) ;
2369  }
2370  else { // staying on Green
2371  R = *(src+Mask[3]);
2372  G = *src;
2373  B = (*(src+Mask[6]) ) ;
2374  }
2375  }
2376  else {
2377  if ((dest.GetWidth()-1)%2 == xoffset) { // staying on Green
2378  R = ( *(src+Mask[6]) ) ;
2379  G = *src;
2380  B = *(src+Mask[3]) ;
2381  }
2382  else { // staying on Blue
2383  R = *(src+Mask[5]);
2384  G = ( *(src+Mask[3]) + *(src+Mask[6]) ) /2;
2385  B = *src;
2386  }
2387  }
2388  *sink++ =R;
2389  *sink++ =G;
2390  *sink++ =B;
2391  src++;
2392 
2393 
2394  //loop
2395  for (unsigned int y=1; y<(unsigned int)source.GetHeight()-1; y++) {
2396  // first pixel in line
2397  if (y%2 == yoffset)
2398  if (0%2 == xoffset) { // staying on Red
2399  R = *src;
2400  G = (*(src+Mask[1]) + *(src+Mask[4]) + *(src+Mask[6]) ) /3;
2401  B = ( *(src+Mask[2]) + *(src+Mask[7])) /2;
2402  } else { // staying on Green
2403  R = *(src+Mask[4]);
2404  G = *src;
2405  B = ( *(src+Mask[1]) + *(src+Mask[6]) ) /2;
2406  }
2407  else
2408  if (0 == xoffset) { // staying on Green
2409  R = ( *(src+Mask[1]) + *(src+Mask[6]) ) /2;
2410  G = *src;
2411  B = *(src+Mask[4]);
2412  }
2413  else { // staying on Blue
2414  R = ( *(src+Mask[0]) + *(src+Mask[7])) /2;
2415  G = (*(src+Mask[1]) + *(src+Mask[4]) + *(src+Mask[6]) ) /3;
2416  B = *src;
2417  }
2418  *sink++ =R;
2419  *sink++ =G;
2420  *sink++ =B;
2421  src++;
2422  // main part of line
2423  for (unsigned int x=1; x<(unsigned int)source.GetWidth()-1; x++) {
2424  if (y%2 == yoffset)
2425  if (x%2 == xoffset) { // staying on Red
2426  R = *src;
2427  G = (*(src+Mask[1]) + *(src+Mask[3])
2428  + *(src+Mask[4]) + *(src+Mask[6]) ) /4;
2429  B = ( *(src+Mask[0]) + *(src+Mask[2])
2430  + *(src+Mask[5]) + *(src+Mask[7])) /4;
2431  } else { // staying on Green
2432  R = ( *(src+Mask[3]) + *(src+Mask[4]) ) /2;
2433  G = *src;
2434  B = ( *(src+Mask[1]) + *(src+Mask[6]) ) /2;
2435  }
2436  else
2437  if (x%2 == xoffset) { // staying on Green
2438  R = ( *(src+Mask[1]) + *(src+Mask[6]) ) /2;
2439  G = *src;
2440  B = ( *(src+Mask[3]) + *(src+Mask[4]) ) /2;
2441  }
2442  else { // staying on Blue
2443  R = ( *(src+Mask[0]) + *(src+Mask[2])
2444  + *(src+Mask[5]) + *(src+Mask[7])) /4;
2445  G = (*(src+Mask[1]) + *(src+Mask[3])
2446  + *(src+Mask[4]) + *(src+Mask[6]) ) /4;
2447  B = *src;
2448  }
2449  *sink++ =R;
2450  *sink++ =G;
2451  *sink++ =B;
2452  src++;
2453  }
2454  // last pixel in line
2455  if (y%2 == yoffset)
2456  if ((srcskip-1)%2 == xoffset) { // staying on Red
2457  R = *src;
2458  G = (*(src+Mask[1]) + *(src+Mask[3]) + *(src+Mask[6]) ) /3;
2459  B = ( *(src+Mask[0]) + *(src+Mask[5])) /2;
2460  } else { // staying on Green
2461  R = *(src+Mask[3]) ;
2462  G = *src;
2463  B = ( *(src+Mask[1]) + *(src+Mask[6]) ) /2;
2464  }
2465  else
2466  if ((srcskip-1)%2 == xoffset) { // staying on Green
2467  R = ( *(src+Mask[1]) + *(src+Mask[6]) ) /2;
2468  G = *src;
2469  B = *(src+Mask[3]);
2470  }
2471  else { // staying on Blue
2472  R = ( *(src+Mask[0]) + *(src+Mask[5])) /2;
2473  G = (*(src+Mask[1]) + *(src+Mask[3])+ *(src+Mask[6]) ) /3;
2474  B = *src;
2475  }
2476  *sink++ =R;
2477  *sink++ =G;
2478  *sink++ =B;
2479  src++;
2480 
2481 
2482  }
2483  // first pixel in last line
2484  if ((source.GetHeight()-1)%2 == yoffset) {
2485  if (0 == xoffset) { // staying on Red
2486  R = *src;
2487  G = ( *(src+Mask[1])+ *(src+Mask[4]) ) /2;
2488  B = *(src+Mask[2]) ;
2489  }
2490  else { // staying on Green
2491  R = *(src+Mask[4]);
2492  G = *src;
2493  B = (*(src+Mask[1]) ) ;
2494  }
2495  }
2496  else {
2497  if (0 == xoffset) { // staying on Green
2498  R = ( *(src+Mask[1]) ) ;
2499  G = *src;
2500  B = *(src+Mask[4]) ;
2501  }
2502  else { // staying on Blue
2503  R = *(src+Mask[2]);
2504  G = ( *(src+Mask[1]) + *(src+Mask[4]) ) /2;
2505  B = *src;
2506  }
2507  }
2508  *sink++ =R;
2509  *sink++ =G;
2510  *sink++ =B;
2511  src++;
2512  // last line
2513  if ((source.GetHeight()-1)%2 == yoffset) {
2514  for (unsigned int x=1; x<(unsigned int)dest.GetWidth()-1; x++){
2515  if (x%2 == xoffset) { // staying on Red
2516  R = *src;
2517  G = ( *(src+Mask[3])+ *(src+Mask[1]) + *(src+Mask[4]) ) /3;
2518  B = ( *(src+Mask[0]) + *(src+Mask[2])) /2;
2519  }
2520  else { // staying on Green
2521  R = ( *(src+Mask[3]) + *(src+Mask[4]) ) /2;
2522  G = *src;
2523  B = (*(src+Mask[1]) ) ;
2524  }
2525  *sink++ =R;
2526  *sink++ =G;
2527  *sink++ =B;
2528  src++;
2529  }
2530  }
2531  else {
2532  for (unsigned int x=1; x<(unsigned int)dest.GetWidth()-1; x++){
2533  if (x%2 == xoffset) { // staying on Green
2534  R = ( *(src+Mask[1]) ) ;
2535  G = *src;
2536  B = ( *(src+Mask[3]) + *(src+Mask[4]) ) /2;
2537  }
2538  else { // staying on Blue
2539  R = ( *(src+Mask[0]) + *(src+Mask[2])) /2;
2540  G = ( *(src+Mask[1]) + *(src+Mask[3]) + *(src+Mask[4]) ) /3;
2541  B = *src;
2542  }
2543  *sink++ =R;
2544  *sink++ =G;
2545  *sink++ =B;
2546  src++;
2547  }
2548  }
2549  // last pixel in last line
2550  if ((source.GetHeight()-1)%2 == yoffset) {
2551  if ((dest.GetWidth()-1)%2 == xoffset) { // staying on Red
2552  R = *src;
2553  G = ( *(src+Mask[3])+ *(src+Mask[1]) ) /2;
2554  B = *(src+Mask[0]) ;
2555  }
2556  else { // staying on Green
2557  R = *(src+Mask[3]);
2558  G = *src;
2559  B = (*(src+Mask[1]) ) ;
2560  }
2561  }
2562  else {
2563  if ((dest.GetWidth()-1)%2 == xoffset) { // staying on Green
2564  R = ( *(src+Mask[1]) ) ;
2565  G = *src;
2566  B = *(src+Mask[3]) ;
2567  }
2568  else { // staying on Blue
2569  R = *(src+Mask[0]);
2570  G = ( *(src+Mask[3]) + *(src+Mask[1]) ) /2;
2571  B = *src;
2572  }
2573  }
2574  *sink++ =R;
2575  *sink++ =G;
2576  *sink++ =B;
2577  src++;
2578 
2579 
2580  return 0;
2581 }
2582 
2583 template <class StorageType>
2585 {
2586  switch(method){
2588  if(source.GetStorageType() == ImageBase::ST_unsignedchar){
2589  BayerToRGBSimple_((unsigned char*)source.GetImageData(),(unsigned char*)dest.GetImageData(),
2590  source.GetWidth(),source.GetHeight(),source.GetColorModel());
2591  }else if(source.GetStorageType() == ImageBase::ST_unsignedchar){
2592  BayerToRGBSimple_((unsigned short*)source.GetImageData(),(unsigned short*)dest.GetImageData(),
2593  source.GetWidth(),source.GetHeight(),source.GetColorModel());
2594  }else{
2595  BIASERR("ONLY IMPLEMENTED FOR unsigned char and unsigned short");
2596  }
2597  break;
2599  BayerToRGBNearestNeighbour_(source.GetImageData(),dest.GetImageData(),
2600  source.GetWidth(),source.GetHeight(),source.GetColorModel());
2601  break;
2603  if(source.GetStorageType() == ImageBase::ST_unsignedchar){
2604  BayerToRGBBilinear_((unsigned char*)source.GetImageData(),(unsigned char*)dest.GetImageData(),
2605  source.GetWidth(),source.GetHeight(),source.GetColorModel());
2606  }else if(source.GetStorageType() == ImageBase::ST_unsignedchar){
2607  BayerToRGBBilinear_((unsigned short*)source.GetImageData(),(unsigned short*)dest.GetImageData(),
2608  source.GetWidth(),source.GetHeight(),source.GetColorModel());
2609  }else{
2610  BIASERR("ONLY IMPLEMENTED FOR unsigned char and unsigned short");
2611  }
2612  break;
2614  if(source.GetStorageType() == ImageBase::ST_unsignedchar){
2615  BayerToRGBHQLinear_((unsigned char*)source.GetImageData(),(unsigned char*)dest.GetImageData(),
2616  source.GetWidth(),source.GetHeight(),source.GetColorModel());
2617  }else if(source.GetStorageType() == ImageBase::ST_unsignedchar){
2618  BayerToRGBHQLinear_((unsigned short*)source.GetImageData(),(unsigned short*)dest.GetImageData(),
2619  source.GetWidth(),source.GetHeight(),source.GetColorModel(),source.GetBitDepth());
2620  }else{
2621  BIASERR("ONLY IMPLEMENTED FOR unsigned char and unsigned short");
2622  }
2623  break;
2625  BIASERR("NOT IMPLEMENTED");
2626  break;
2627 
2629  BIASERR("NOT IMPLEMENTED YET");
2630  break;
2631 
2632  default:
2633  BIASERR("NO DEFAULT OPERATION");
2634  break;
2635  }
2636 
2637  if(flip)
2638  dest.FlipHorizontal();
2639 
2640  return 0;
2641 
2642 }
2643 
2644 
2645 
2646 
2647 
2648 
2649 // 2 pixel border in dest is black
2650 template <class StorageType>
2652  Image<StorageType>& dest )
2653 {
2654  BIASGDOUT(D_CONVERT," Image::BayerToRGBSlow_()");
2655 
2656  StorageType *sink = dest.GetImageData() + 2 * dest.GetWidthStep() + 6;
2657  const StorageType *src = source.GetImageData() + 2 * source.GetWidth() + 2;
2658 
2659  int Mask[12];
2660  StorageType R,G,B, d1, d2;
2661 
2662  Mask[0] = - (int(source.GetWidth()) +1);
2663  Mask[1] = - int(source.GetWidth());
2664  Mask[2] = - (int(source.GetWidth()) -1);
2665  Mask[3] = -1;
2666  Mask[4] = +1;
2667  Mask[5] = int(source.GetWidth()) -1;
2668  Mask[6] = + int(source.GetWidth());
2669  Mask[7] = int(source.GetWidth()) +1;
2670  Mask[8] = - 2 * int(source.GetWidth());
2671  Mask[9] = - 2 ;
2672  Mask[10] = + 2 ;
2673  Mask[11] = + 2 * int(source.GetWidth());
2674 
2675 #define D1 (*(src+Mask[8])>*(src+Mask[11]))?\
2676  (*(src+Mask[8])-*(src+Mask[11])):\
2677  (*(src+Mask[11])-*(src+Mask[8]))
2678 #define D2 (*(src+Mask[9])>*(src+Mask[10]))?\
2679  (*(src+Mask[9])-*(src+Mask[10])):\
2680  (*(src+Mask[10])-*(src+Mask[9]))
2681 
2682  unsigned int xoffset = 0;
2683  unsigned int yoffset = 0;
2684  switch (source.GetColorModel()) {
2685  case ImageBase::CM_Bayer_GBRG: yoffset = 1; break;
2686  case ImageBase::CM_Bayer_GRBG: xoffset = 1; break;
2687  case ImageBase::CM_Bayer_BGGR: xoffset = 1;yoffset = 1; break;
2688  default:; }
2689 
2690  for (unsigned int y=2; y<(unsigned int)source.GetHeight()-2; y++) {
2691  for (unsigned int x=2; x<(unsigned int)source.GetWidth()-2; x++) {
2692  if (y%2 == yoffset)
2693  if (x%2 == xoffset) { // staying on Red
2694  R = *src;
2695  d1 = D1;
2696  d2 = D2;
2697  if (d1<d2){
2698  G = (*(src+Mask[1]) + *(src+Mask[6]) ) /2;
2699  } else if (d2<d1){
2700  G = (*(src+Mask[3]) + *(src+Mask[4]) ) /2;
2701  } else {
2702  G = (*(src+Mask[1]) + *(src+Mask[3])
2703  + *(src+Mask[4]) + *(src+Mask[6]) ) /4;
2704  }
2705  B = ( *(src+Mask[0]) + *(src+Mask[2])
2706  + *(src+Mask[5]) + *(src+Mask[7])) /4;
2707  }
2708  else { // staying on Green
2709  R = ( *(src+Mask[3]) + *(src+Mask[4]) ) /2;
2710  G = *src;
2711  B = ( *(src+Mask[1]) + *(src+Mask[6]) ) /2;
2712  }
2713  else
2714  if (x%2 == xoffset) { // staying on Green
2715  R = ( *(src+Mask[1]) + *(src+Mask[6]) ) /2;
2716  G = *src;
2717  B = ( *(src+Mask[3]) + *(src+Mask[4]) ) /2;
2718  }
2719  else { // staying on Blue
2720  R = ( *(src+Mask[0]) + *(src+Mask[2])
2721  + *(src+Mask[5]) + *(src+Mask[7])) /4;
2722  d1 = D1;
2723  d2 = D2;
2724  if (d1<d2){
2725  G = (*(src+Mask[1]) + *(src+Mask[6]) ) /2;
2726  } else if (d2<d1){
2727  G = (*(src+Mask[3]) + *(src+Mask[4]) ) /2;
2728  } else {
2729  G = (*(src+Mask[1]) + *(src+Mask[3])
2730  + *(src+Mask[4]) + *(src+Mask[6]) ) /4;
2731  }
2732  B = *src;
2733  }
2734  *sink++ =R;
2735  *sink++ =G;
2736  *sink++ =B;
2737  src++;
2738  }
2739  sink += 12;
2740  src += 4;
2741  }
2742  dest.SetROI(2,2,dest.GetWidth()-2,dest.GetHeight()-2);
2743  return 0;
2744 }
2745 
2746 template <class StorageType>
2748  Image<StorageType>& dest )
2749 {
2750  StorageType *sink = dest.GetImageData() ;
2751  const StorageType *src = source.GetImageData() ;
2752  float y,u = 0.0,v=0.0;
2753  float r,g,b;
2754  int uoffset=0 ;
2755  int voffset=0 ;
2756  int width = source.GetWidth();
2757  int height = source.GetHeight();
2758 
2759  for (int z = 0; z < height ; z++) {
2760  if (z%2==0) {
2761  voffset = width*height +z/2*width/2;
2762  uoffset = width*height + width*height/4+z/2*width/2;
2763  }
2764  for (int x=0; x< width; x++) {
2765  y = 1.164f * (float) (src[z*width + x] -16) ;
2766  if ( x%2==0 ) {
2767  v = (float) (src[voffset + x/2] -128);
2768  u = (float) (src[uoffset + x/2 ] -128);
2769  }
2770  b = float(rint( y + 2.018f*v ));
2771  g = float(rint( y - 0.813f*u - 0.391f*v));
2772  r = float(rint( y + 1.596f*u));
2773  if (r>255) r=255;
2774  if (g>255) g=255;
2775  if (b>255) b=255;
2776  if (r<0) r = 0;
2777  if (g<0) g = 0;
2778  if (b<0) b = 0;
2779 
2780  sink[(z*width + x)*3 ] = (unsigned char) r;
2781  sink[(z*width + x)*3 +1] =(unsigned char)g;
2782  sink[(z*width + x)*3 +2] =(unsigned char) b;
2783  }
2784  }
2785  return 0;
2786 }
2787 
2788 template <class StorageType>
2790  Image<StorageType>& dest )
2791 {
2792  StorageType *sink = dest.GetImageData() ;
2793  const StorageType *src = source.GetImageData() ;
2794 
2795  int width = source.GetWidth();
2796  int height = source.GetHeight();
2797 
2798  for (int z = 0; z < height ; z++)
2799  for (int x=0; x< width; x++)
2800  sink[(z*width + x) ] = src[z*width + x];
2801 
2802  return 0;
2803 }
2804 
2805 
2806 template <class StorageType>
2808  Image<StorageType>& dest )
2809 {
2810  StorageType *sink = dest.GetImageData() ;
2811  const StorageType *src = source.GetImageData() ;
2812 
2813  int width = source.GetWidth();
2814  int height = source.GetHeight();
2815 
2816  for (int z = 0; z < height ; z++)
2817  for (int x=0; x< width; x++)
2818  sink[(z*width + x) ] = src[z*width*2 + x*2];
2819 
2820  return 0;
2821 }
2822 
2823 
2824 
2825 
2826 int ImageConvert::FloatToUC_(const ImageBase &source, ImageBase &dest)
2827 {
2828  unsigned int values = source.GetPixelCount() * source.GetChannelCount();
2829 
2830  unsigned char *d = (unsigned char*)dest.GetImageData();
2831  float *s =(float*) source.GetImageData();
2832  for (unsigned int i=0; i<values; i++){
2833  d[i] = (unsigned char) *s;
2834  s ++;
2835  }
2836 
2837  return 0;
2838 }
2839 
2840 
2841 int ImageConvert::ConvertST(const ImageBase &source, ImageBase &dest,
2842  ImageBase::EStorageType targetST)
2843 {
2844  // re-initialize target image
2845  if (!dest.IsEmpty()) {
2846  dest.Release();
2847  }
2848  dest.Init(source.GetWidth(), source.GetHeight(), source.GetChannelCount(), targetST);
2849 
2850  // return error when storare type is invalid
2851  const ImageBase::EStorageType sourceST = source.GetStorageType();
2852  if (targetST == ImageBase::ST_invalid || sourceST == ImageBase::ST_invalid) {
2853  BIASERR("Invalid storage type in source or target image!");
2854  return -1;
2855  }
2856 
2857  // simply copy data if source and target storage type is identical
2858  if (targetST == sourceST) {
2859  dest = source;
2860  return 0;
2861  }
2862 
2863  // copy color model to target image
2864  dest.SetColorModel(source.GetColorModel());
2865 
2866  // copy converted values to target image
2867  unsigned int values = source.GetPixelCount() * source.GetChannelCount();
2868  switch (targetST)
2869  {
2870 #ifdef BUILD_IMAGE_FLOAT
2871  case ImageBase::ST_float:
2872  {
2873  float* d = (float*) dest.GetImageData();
2874  switch (sourceST)
2875  {
2876 # ifdef BUILD_IMAGE_DOUBLE
2877  case ImageBase::ST_double:
2878  {
2879  double* s = (double*) source.GetImageData();
2880  for (unsigned int i = 0; i < values; i++) d[i] = (float) s[i];
2881  }
2882  break;
2883 # endif
2884 # ifdef BUILD_IMAGE_UCHAR
2885  case ImageBase::ST_unsignedchar:
2886  {
2887  unsigned char *s = (unsigned char*) source.GetImageData();
2888  for (unsigned int i = 0; i < values; i++) d[i] = (float) s[i];
2889  }
2890  break;
2891 # endif
2892 # ifdef BUILD_IMAGE_CHAR
2893  case ImageBase::ST_char:
2894  {
2895  char *s = (char*) source.GetImageData();
2896  for (unsigned int i = 0; i < values; i++) d[i] = (float) s[i];
2897  }
2898  break;
2899 # endif
2900 # ifdef BUILD_IMAGE_USHORT
2901  case ImageBase::ST_unsignedshortint:
2902  {
2903  unsigned short *s = (unsigned short*) source.GetImageData();
2904  for (unsigned int i = 0; i < values; i++) d[i] = (float) s[i];
2905  }
2906  break;
2907 # endif
2908 # ifdef BUILD_IMAGE_SHORT
2909  case ImageBase::ST_shortint:
2910  {
2911  short *s = (short*) source.GetImageData();
2912  for (unsigned int i = 0; i < values; i++) d[i] = (float) s[i];
2913  }
2914  break;
2915 # endif
2916 # ifdef BUILD_IMAGE_UINT
2917  case ImageBase::ST_unsignedint:
2918  {
2919  unsigned int *s = (unsigned int*) source.GetImageData();
2920  for (unsigned int i = 0; i < values; i++) d[i] = (float) s[i];
2921  }
2922  break;
2923 # endif
2924 # ifdef BUILD_IMAGE_INT
2925  case ImageBase::ST_int:
2926  {
2927  int *s = (int*) source.GetImageData();
2928  for (unsigned int i = 0; i < values; i++) d[i] = (float) s[i];
2929  }
2930  break;
2931 # endif
2932  default:
2933  memset(dest.GetImageData(), 0, values * sizeof(float));
2934  BIASERR("ConvertST() not implemented for sourceST = " << sourceST
2935  << " and targetST = " << targetST << "!");
2936  return -1;
2937  }
2938  }
2939  break;
2940 #endif // BUILD_IMAGE_FLOAT
2941 
2942 #ifdef BUILD_IMAGE_DOUBLE
2943  case ImageBase::ST_double:
2944  {
2945  double* d = (double*) dest.GetImageData();
2946  switch (sourceST)
2947  {
2948 # ifdef BUILD_IMAGE_FLOAT
2949  case ImageBase::ST_float:
2950  {
2951  float* s = (float*) source.GetImageData();
2952  for (unsigned int i = 0; i < values; i++) d[i] = (double) s[i];
2953  }
2954  break;
2955 # endif
2956 # ifdef BUILD_IMAGE_UCHAR
2957  case ImageBase::ST_unsignedchar:
2958  {
2959  unsigned char *s = (unsigned char*) source.GetImageData();
2960  for (unsigned int i = 0; i < values; i++) d[i] = (double) s[i];
2961  }
2962  break;
2963 # endif
2964 # ifdef BUILD_IMAGE_CHAR
2965  case ImageBase::ST_char:
2966  {
2967  char *s = (char*) source.GetImageData();
2968  for (unsigned int i = 0; i < values; i++) d[i] = (double) s[i];
2969  }
2970  break;
2971 # endif
2972 # ifdef BUILD_IMAGE_USHORT
2973  case ImageBase::ST_unsignedshortint:
2974  {
2975  unsigned short *s = (unsigned short*) source.GetImageData();
2976  for (unsigned int i = 0; i < values; i++) d[i] = (double) s[i];
2977  }
2978  break;
2979 # endif
2980 # ifdef BUILD_IMAGE_SHORT
2981  case ImageBase::ST_shortint:
2982  {
2983  short *s = (short*) source.GetImageData();
2984  for (unsigned int i = 0; i < values; i++) d[i] = (double) s[i];
2985  }
2986  break;
2987 # endif
2988 # ifdef BUILD_IMAGE_UINT
2989  case ImageBase::ST_unsignedint:
2990  {
2991  unsigned int *s = (unsigned int*) source.GetImageData();
2992  for (unsigned int i = 0; i < values; i++) d[i] = (double) s[i];
2993  }
2994  break;
2995 # endif
2996 # ifdef BUILD_IMAGE_INT
2997  case ImageBase::ST_int:
2998  {
2999  int *s = (int*) source.GetImageData();
3000  for (unsigned int i = 0; i < values; i++) d[i] = (double) s[i];
3001  }
3002  break;
3003 # endif
3004  default:
3005  memset(dest.GetImageData(), 0, values * sizeof(double));
3006  BIASERR("ConvertST() not implemented for sourceST = " << sourceST
3007  << " and targetST = " << targetST << "!");
3008  return -1;
3009  }
3010  }
3011  break;
3012 #endif // BUILD_IMAGE_DOUBLE
3013 
3014 #ifdef BUILD_IMAGE_UCHAR
3015  case ImageBase::ST_unsignedchar:
3016  {
3017  unsigned char* d = (unsigned char*) dest.GetImageData();
3018  switch (sourceST)
3019  {
3020 # ifdef BUILD_IMAGE_FLOAT
3021  case ImageBase::ST_float:
3022  {
3023  float* s = (float*) source.GetImageData();
3024  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned char) s[i];
3025  }
3026  break;
3027 # endif
3028 # ifdef BUILD_IMAGE_DOUBLE
3029  case ImageBase::ST_double:
3030  {
3031  double* s = (double*) source.GetImageData();
3032  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned char) s[i];
3033  }
3034  break;
3035 # endif
3036 # ifdef BUILD_IMAGE_CHAR
3037  case ImageBase::ST_char:
3038  {
3039  char *s = (char*) source.GetImageData();
3040  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned char) s[i];
3041  }
3042  break;
3043 # endif
3044 # ifdef BUILD_IMAGE_USHORT
3045  case ImageBase::ST_unsignedshortint:
3046  {
3047  unsigned short *s = (unsigned short*) source.GetImageData();
3048  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned char) s[i];
3049  }
3050  break;
3051 # endif
3052 # ifdef BUILD_IMAGE_SHORT
3053  case ImageBase::ST_shortint:
3054  {
3055  short *s = (short*) source.GetImageData();
3056  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned char) s[i];
3057  }
3058  break;
3059 # endif
3060 # ifdef BUILD_IMAGE_UINT
3061  case ImageBase::ST_unsignedint:
3062  {
3063  unsigned int *s = (unsigned int*) source.GetImageData();
3064  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned char) s[i];
3065  }
3066  break;
3067 # endif
3068 # ifdef BUILD_IMAGE_INT
3069  case ImageBase::ST_int:
3070  {
3071  int *s = (int*) source.GetImageData();
3072  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned char) s[i];
3073  }
3074  break;
3075 # endif
3076  default:
3077  memset(dest.GetImageData(), 0, values * sizeof(unsigned char));
3078  BIASERR("ConvertST() not implemented for sourceST = " << sourceST
3079  << " and targetST = " << targetST << "!");
3080  return -1;
3081  }
3082  }
3083  break;
3084 #endif // BUILD_IMAGE_UCHAR
3085 
3086 #ifdef BUILD_IMAGE_CHAR
3087  case ImageBase::ST_char:
3088  {
3089  char* d = (char*) dest.GetImageData();
3090  switch (sourceST)
3091  {
3092 # ifdef BUILD_IMAGE_FLOAT
3093  case ImageBase::ST_float:
3094  {
3095  float* s = (float*) source.GetImageData();
3096  for (unsigned int i = 0; i < values; i++) d[i] = (char) s[i];
3097  }
3098  break;
3099 # endif
3100 # ifdef BUILD_IMAGE_DOUBLE
3101  case ImageBase::ST_double:
3102  {
3103  double* s = (double*) source.GetImageData();
3104  for (unsigned int i = 0; i < values; i++) d[i] = (char) s[i];
3105  }
3106  break;
3107 # endif
3108 # ifdef BUILD_IMAGE_UCHAR
3109  case ImageBase::ST_unsignedchar:
3110  {
3111  unsigned char *s = (unsigned char*) source.GetImageData();
3112  for (unsigned int i = 0; i < values; i++) d[i] = (char) s[i];
3113  }
3114  break;
3115 # endif
3116 # ifdef BUILD_IMAGE_USHORT
3117  case ImageBase::ST_unsignedshortint:
3118  {
3119  unsigned short *s = (unsigned short*) source.GetImageData();
3120  for (unsigned int i = 0; i < values; i++) d[i] = (char) s[i];
3121  }
3122  break;
3123 # endif
3124 # ifdef BUILD_IMAGE_SHORT
3125  case ImageBase::ST_shortint:
3126  {
3127  short *s = (short*) source.GetImageData();
3128  for (unsigned int i = 0; i < values; i++) d[i] = (char) s[i];
3129  }
3130  break;
3131 # endif
3132 # ifdef BUILD_IMAGE_UINT
3133  case ImageBase::ST_unsignedint:
3134  {
3135  unsigned int *s = (unsigned int*) source.GetImageData();
3136  for (unsigned int i = 0; i < values; i++) d[i] = (char) s[i];
3137  }
3138  break;
3139 # endif
3140 # ifdef BUILD_IMAGE_INT
3141  case ImageBase::ST_int:
3142  {
3143  int *s = (int*) source.GetImageData();
3144  for (unsigned int i = 0; i < values; i++) d[i] = (char) s[i];
3145  }
3146  break;
3147 # endif
3148  default:
3149  memset(dest.GetImageData(), 0, values * sizeof(char));
3150  BIASERR("ConvertST() not implemented for sourceST = " << sourceST
3151  << " and targetST = " << targetST << "!");
3152  return -1;
3153  }
3154  }
3155  break;
3156 #endif // BUILD_IMAGE_CHAR
3157 
3158 #ifdef BUILD_IMAGE_USHORT
3159  case ImageBase::ST_unsignedshortint:
3160  {
3161  unsigned short* d = (unsigned short*) dest.GetImageData();
3162  switch (sourceST)
3163  {
3164 # ifdef BUILD_IMAGE_FLOAT
3165  case ImageBase::ST_float:
3166  {
3167  float* s = (float*) source.GetImageData();
3168  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned short) s[i];
3169  }
3170  break;
3171 # endif
3172 # ifdef BUILD_IMAGE_DOUBLE
3173  case ImageBase::ST_double:
3174  {
3175  double* s = (double*) source.GetImageData();
3176  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned short) s[i];
3177  }
3178  break;
3179 # endif
3180 # ifdef BUILD_IMAGE_UCHAR
3181  case ImageBase::ST_unsignedchar:
3182  {
3183  unsigned char *s = (unsigned char*) source.GetImageData();
3184  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned short) s[i];
3185  }
3186  break;
3187 # endif
3188 # ifdef BUILD_IMAGE_CHAR
3189  case ImageBase::ST_char:
3190  {
3191  char *s = (char*) source.GetImageData();
3192  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned short) s[i];
3193  }
3194  break;
3195 # endif
3196 # ifdef BUILD_IMAGE_SHORT
3197  case ImageBase::ST_shortint:
3198  {
3199  short *s = (short*) source.GetImageData();
3200  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned short) s[i];
3201  }
3202  break;
3203 # endif
3204 # ifdef BUILD_IMAGE_UINT
3205  case ImageBase::ST_unsignedint:
3206  {
3207  unsigned int *s = (unsigned int*) source.GetImageData();
3208  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned short) s[i];
3209  }
3210  break;
3211 # endif
3212 # ifdef BUILD_IMAGE_INT
3213  case ImageBase::ST_int:
3214  {
3215  int *s = (int*) source.GetImageData();
3216  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned short) s[i];
3217  }
3218  break;
3219 # endif
3220  default:
3221  memset(dest.GetImageData(), 0, values * sizeof(unsigned short));
3222  BIASERR("ConvertST() not implemented for sourceST = " << sourceST
3223  << " and targetST = " << targetST << "!");
3224  return -1;
3225  }
3226  }
3227  break;
3228 #endif // BUILD_IMAGE_USHORT
3229 
3230 #ifdef BUILD_IMAGE_SHORT
3231  case ImageBase::ST_shortint:
3232  {
3233  short* d = (short*) dest.GetImageData();
3234  switch (sourceST)
3235  {
3236 # ifdef BUILD_IMAGE_FLOAT
3237  case ImageBase::ST_float:
3238  {
3239  float* s = (float*) source.GetImageData();
3240  for (unsigned int i = 0; i < values; i++) d[i] = (short) s[i];
3241  }
3242  break;
3243 # endif
3244 # ifdef BUILD_IMAGE_DOUBLE
3245  case ImageBase::ST_double:
3246  {
3247  double* s = (double*) source.GetImageData();
3248  for (unsigned int i = 0; i < values; i++) d[i] = (short) s[i];
3249  }
3250  break;
3251 # endif
3252 # ifdef BUILD_IMAGE_UCHAR
3253  case ImageBase::ST_unsignedchar:
3254  {
3255  unsigned char *s = (unsigned char*) source.GetImageData();
3256  for (unsigned int i = 0; i < values; i++) d[i] = (short) s[i];
3257  }
3258  break;
3259 # endif
3260 # ifdef BUILD_IMAGE_CHAR
3261  case ImageBase::ST_char:
3262  {
3263  char *s = (char*) source.GetImageData();
3264  for (unsigned int i = 0; i < values; i++) d[i] = (short) s[i];
3265  }
3266  break;
3267 # endif
3268 # ifdef BUILD_IMAGE_USHORT
3269  case ImageBase::ST_unsignedshortint:
3270  {
3271  unsigned short *s = (unsigned short*) source.GetImageData();
3272  for (unsigned int i = 0; i < values; i++) d[i] = (short) s[i];
3273  }
3274  break;
3275 # endif
3276 # ifdef BUILD_IMAGE_UINT
3277  case ImageBase::ST_unsignedint:
3278  {
3279  unsigned int *s = (unsigned int*) source.GetImageData();
3280  for (unsigned int i = 0; i < values; i++) d[i] = (short) s[i];
3281  }
3282  break;
3283 # endif
3284 # ifdef BUILD_IMAGE_INT
3285  case ImageBase::ST_int:
3286  {
3287  int *s = (int*) source.GetImageData();
3288  for (unsigned int i = 0; i < values; i++) d[i] = (short) s[i];
3289  }
3290  break;
3291 # endif
3292  default:
3293  memset(dest.GetImageData(), 0, values * sizeof(short));
3294  BIASERR("ConvertST() not implemented for sourceST = " << sourceST
3295  << " and targetST = " << targetST << "!");
3296  return -1;
3297  }
3298  }
3299  break;
3300 #endif // BUILD_IMAGE_SHORT
3301 
3302 #ifdef BUILD_IMAGE_UINT
3303  case ImageBase::ST_unsignedint:
3304  {
3305  unsigned int* d = (unsigned int*) dest.GetImageData();
3306  switch (sourceST)
3307  {
3308 # ifdef BUILD_IMAGE_FLOAT
3309  case ImageBase::ST_float:
3310  {
3311  float* s = (float*) source.GetImageData();
3312  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned int) s[i];
3313  }
3314  break;
3315 # endif
3316 # ifdef BUILD_IMAGE_DOUBLE
3317  case ImageBase::ST_double:
3318  {
3319  double* s = (double*) source.GetImageData();
3320  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned int) s[i];
3321  }
3322  break;
3323 # endif
3324 # ifdef BUILD_IMAGE_UCHAR
3325  case ImageBase::ST_unsignedchar:
3326  {
3327  unsigned char *s = (unsigned char*) source.GetImageData();
3328  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned int) s[i];
3329  }
3330  break;
3331 # endif
3332 # ifdef BUILD_IMAGE_CHAR
3333  case ImageBase::ST_char:
3334  {
3335  char *s = (char*) source.GetImageData();
3336  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned int) s[i];
3337  }
3338  break;
3339 # endif
3340 # ifdef BUILD_IMAGE_USHORT
3341  case ImageBase::ST_unsignedshortint:
3342  {
3343  unsigned short *s = (unsigned short*) source.GetImageData();
3344  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned int) s[i];
3345  }
3346  break;
3347 # endif
3348 # ifdef BUILD_IMAGE_SHORT
3349  case ImageBase::ST_shortint:
3350  {
3351  short *s = (short*) source.GetImageData();
3352  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned int) s[i];
3353  }
3354  break;
3355 # endif
3356 # ifdef BUILD_IMAGE_INT
3357  case ImageBase::ST_int:
3358  {
3359  int *s = (int*) source.GetImageData();
3360  for (unsigned int i = 0; i < values; i++) d[i] = (unsigned int) s[i];
3361  }
3362  break;
3363 # endif
3364  default:
3365  memset(dest.GetImageData(), 0, values * sizeof(unsigned int));
3366  BIASERR("ConvertST() not implemented for sourceST = " << sourceST
3367  << " and targetST = " << targetST << "!");
3368  return -1;
3369  }
3370  }
3371  break;
3372 #endif // BUILD_IMAGE_UINT
3373 
3374 #ifdef BUILD_IMAGE_INT
3375  case ImageBase::ST_int:
3376  {
3377  int* d = (int*) dest.GetImageData();
3378  switch (sourceST)
3379  {
3380 # ifdef BUILD_IMAGE_FLOAT
3381  case ImageBase::ST_float:
3382  {
3383  float* s = (float*) source.GetImageData();
3384  for (unsigned int i = 0; i < values; i++) d[i] = (int) s[i];
3385  }
3386  break;
3387 # endif
3388 # ifdef BUILD_IMAGE_DOUBLE
3389  case ImageBase::ST_double:
3390  {
3391  double* s = (double*) source.GetImageData();
3392  for (unsigned int i = 0; i < values; i++) d[i] = (int) s[i];
3393  }
3394  break;
3395 # endif
3396 # ifdef BUILD_IMAGE_UCHAR
3397  case ImageBase::ST_unsignedchar:
3398  {
3399  unsigned char *s = (unsigned char*) source.GetImageData();
3400  for (unsigned int i = 0; i < values; i++) d[i] = (int) s[i];
3401  }
3402  break;
3403 # endif
3404 # ifdef BUILD_IMAGE_CHAR
3405  case ImageBase::ST_char:
3406  {
3407  char *s = (char*) source.GetImageData();
3408  for (unsigned int i = 0; i < values; i++) d[i] = (int) s[i];
3409  }
3410  break;
3411 # endif
3412 # ifdef BUILD_IMAGE_USHORT
3413  case ImageBase::ST_unsignedshortint:
3414  {
3415  unsigned short *s = (unsigned short*) source.GetImageData();
3416  for (unsigned int i = 0; i < values; i++) d[i] = (int) s[i];
3417  }
3418  break;
3419 # endif
3420 # ifdef BUILD_IMAGE_SHORT
3421  case ImageBase::ST_shortint:
3422  {
3423  short *s = (short*) source.GetImageData();
3424  for (unsigned int i = 0; i < values; i++) d[i] = (int) s[i];
3425  }
3426  break;
3427 # endif
3428 # ifdef BUILD_IMAGE_UINT
3429  case ImageBase::ST_unsignedint:
3430  {
3431  unsigned int *s = (unsigned int*) source.GetImageData();
3432  for (unsigned int i = 0; i < values; i++) d[i] = (int) s[i];
3433  }
3434  break;
3435 # endif
3436  default:
3437  memset(dest.GetImageData(), 0, values * sizeof(int));
3438  BIASERR("ConvertST() not implemented for sourceST = " << sourceST
3439  << " and targetST = " << targetST << "!");
3440  return -1;
3441  }
3442  }
3443  break;
3444 #endif // BUILD_IMAGE_INT
3445 
3446  default:
3447  BIASERR("ConvertST() not implemented for targetST = " << targetST << "!");
3448  return -1;
3449  }
3450 
3451  // set ROI in target image
3452  int tlx, tly, brx, bry;
3453  source.GetROI()->GetCorners(tlx, tly, brx, bry);
3454  dest.GetROI()->SetCorners(tlx, tly, brx, bry);
3455 
3456  return 0;
3457 }
3458 
3459 
3460 template <class StorageType>
3462  Image<StorageType>& dest)
3463 {
3464  BIASGDOUT(D_CONVERT,"ImageConvert::hsLToGrey_()");
3465  StorageType *p=dest.GetImageData();
3466  const StorageType *h, *s, *L;
3467 
3468  if (source.IsPlanar()){
3469  switch (source.GetColorModel()){
3470  case ImageBase::CM_hsL:
3471  case ImageBase::CM_HSL:
3472  h=source.GetImageData();
3473  s=h+(source.GetWidth()*source.GetHeight());
3474  L=s+(source.GetWidth()*source.GetHeight());
3475  break;
3476  default:
3477  BIASERR("HSLToGrey_ must be called with HSL or hsL ColorModel_");
3478  return -1;
3479  }
3480  for (unsigned int i=0; i < dest.GetWidth()*dest.GetHeight(); i++){
3481  *p=(StorageType)*L;
3482  L++; p++;
3483  }
3484  } else { // interleaved
3485  switch (source.GetColorModel()) {
3486  case ImageBase::CM_hsL:
3487  case ImageBase::CM_HSL:
3488  h=source.GetImageData();
3489  s=h+1;
3490  L=h+2;
3491  break;
3492  default:
3493  BIASERR("HSLToGrey_ must be called with HSL or hsL ColorModel_");
3494  return -1;
3495  }
3496  for (unsigned int i=0; i < dest.GetWidth()*dest.GetHeight(); i++){
3497  *p=(StorageType)(*L);
3498  p++; L+=3;
3499  }
3500  }
3501  return 0;
3502 }
3503 
3504 #ifdef BIAS_HAVE_IMAGEMAGICKLIB
3505 
3507 BIAS2ImageMagick(const ImageBase& input, Magick::Image& image)
3508 {
3509  #ifdef WIN32
3510  //initialize DLL loaded library (not required on Linux but once on Windows)
3511  Magick::InitializeMagick(NULL);
3512  #endif
3513 
3514  // manipulate image information, e.g. compression
3515 
3516  image.colorSpace(sRGBColorspace); // default
3517 
3518  // determine export image format/channels:
3519  std::string pixmap;
3520  switch (input.GetChannelCount())
3521  {
3522  case 1:
3523  pixmap="K";
3524  image.colorSpace(GRAYColorspace); // default
3525  break;
3526  case 2:
3527  pixmap="KA"; break;
3528  case 3:
3529  pixmap="RGB"; break;
3530  case 4:
3531  pixmap="RGBA"; break;
3532  default:
3533  BIASERR("unsupported channelcount. Could not convert image to ImageMagick++");
3534  return -1;
3535  }
3536 
3537  // refine the color space used
3538  // there is a difference between color model and channel order
3539  switch (input.GetColorModel())
3540  {
3542  // color model
3543  //TEST image.colorSpace(RGBColorspace);
3544  // channel order (within colro model)
3545  pixmap="RGB";
3546  break;
3548  image.colorSpace(sRGBColorspace);
3549  pixmap="BGR";
3550  break;
3552  image.colorSpace(sRGBColorspace);
3553  pixmap="RGBA";
3554  break;
3555  //case BIAS::ImageBase::CM::CM_BGBA :
3556  // pixmap="BGRA";
3557  // //image.colorSpace(RGBColorspace);
3558  // break;
3560  pixmap="K";
3561  image.colorSpace(GRAYColorspace);
3562  image.type(GrayscaleType);
3563  break;
3565  pixmap="KA";
3566  //image_info->colorspace=GRAYColorspace;
3567  image.colorSpace(UndefinedColorspace);
3568  image.type(GrayscaleMatteType);
3569  break;
3571  // HSV=HSB (which is different from HSI and HSL!)
3572  image.colorSpace(HSBColorspace);
3573  break;
3575  // HSL=HSI (which is different from HSV nor HSB!)
3576  image.colorSpace(HSLColorspace);
3577  break;
3578  default:
3579  BIASERR("unsupported color model. Please add switch for "<<input.GetColorModel());
3580  }
3581 
3582  // Read a file into image object using Magick++ library function:
3583  unsigned char* p_imageData = (unsigned char*)input.GetImageData();
3584  BIASASSERT(p_imageData!=NULL);
3585 
3586  int depth = 8;
3587  // determine per pixel input/output storagetype:
3588  Magick::StorageType magick_ST=Magick::CharPixel; // default
3589 
3590  // CharPixel, ShortPixel, IntegerPixel, FloatPixel, or DoublePixel
3591  switch (input.GetStorageType())
3592  {
3595  magick_ST=Magick::CharPixel;
3596  depth = (8*sizeof(char)); // usually 8 bit
3597  break;
3600  magick_ST=Magick::ShortPixel;
3601  depth = (8*sizeof(short)); // usually 16bit
3602  break;
3605  magick_ST=Magick::IntegerPixel;
3606  depth = (8*sizeof(int)); // usually 32bit
3607  break;
3609  magick_ST=Magick::FloatPixel;
3610  depth = (8*sizeof(float)); // usually 32bit
3611  break;
3613  magick_ST=Magick::DoublePixel;
3614  depth = (8*sizeof(double)); // usually 64 bit
3615  break;
3616  default:
3617  BIASERR("unsupported input image BIAS StorageType "<<input.GetStorageType() );
3618  };
3619  // create ImageMagick pixel buffer object from our image data:
3620  image.read(input.GetWidth(), // dimension
3621  input.GetHeight(),
3622  pixmap, // output map type. e.g. RGBA
3623  magick_ST, // desired storagetype
3624  p_imageData // pointer to our own data array to be written to disk
3625  );
3626  image.depth(depth); // default depth in bit
3627 
3628  // input depth and switch case depth should match
3629  // check if ImageMagick has enough bits to store our data
3630  if (8*input.GetDepth() != image.depth()){
3631  BIASERR("ImageMagick bitdepth="<<image.depth()
3632  <<" seems to be smaller than requested "<<8*input.GetDepth()<<" bit input"<<endl
3633  <<"Do you use a bit-limited ImageMagick version , e.g. ImageMagick-16bit?"<<endl
3634  <<"You cannot convert this image to ImageMagick Image with your version of ImageMagick due to dynamic range problems!"
3635  );
3636  return -1;
3637  }
3638  BIASASSERT( 8*input.GetDepth() == image.depth() );
3639  //image.write("conversiontest.png");
3640  return 0;
3641 }
3642 //////////////////////////////////////////////////////////////////////////
3644 ImageMagick2BIAS(Magick::Image& image, BIAS::ImageBase& result)
3645 {
3646  #ifdef WIN32
3647  //initialize DLL loaded library (not required on Linux but once on Windows)
3648  Magick::InitializeMagick(NULL);
3649  #endif
3650 
3651  try {
3652  // now extract image info from Magick::Image
3653  unsigned width=(unsigned int)image.columns();
3654  unsigned height=(unsigned int)image.rows();
3655  unsigned bitdepth=(unsigned int)image.depth();
3656  unsigned depth=0;
3657  // bitdepth may ba a fractional part of the Byte depth, eg. 12/15 bits are filled.
3658  while (depth<bitdepth)
3659  depth+=8;
3660 
3661  //this divides by 8 and cuts off rest
3662  //e.g. making 1 from 12 or 2 from 17
3663  depth /= 8; // bit To Byte
3664 
3665  unsigned cc=0; // ChannelCount
3666  //ImageBase::EColorModel cm=ImageBase::CM_invalid;
3667  ImageBase::EStorageType st=ImageBase::ST_invalid;
3668  Magick::StorageType imst=MagickLib::UndefinedPixel;
3669 
3670  /// LibMagick: imcs is RGB even for one channel images (bug?)
3671  Magick::ColorspaceType imcs=image.image()->colorspace;
3672  std::string cm_map="";
3673 
3674  // choose appropriate storage type
3675  switch (depth)
3676  {
3677  case sizeof(unsigned char):
3678  st=ImageBase::ST_unsignedchar;
3679  imst=MagickLib::CharPixel;
3680  break;
3681 #ifdef BUILD_IMAGE_USHORT
3682  case sizeof(unsigned short):
3683  st=ImageBase::ST_unsignedshortint;
3684  imst=MagickLib::ShortPixel;
3685  break;
3686 #endif
3687  case sizeof(float): // TODO This could also be int!
3688  st=ImageBase::ST_float;
3689  imst=MagickLib::FloatPixel;
3690  break;
3691  default:
3692  BIASERR("Invalid depth "<<depth<<" byte given (maybe unfinished code)!");
3693 
3694  //very strange behaviour, bitdepth varies on different computers /virtual machines
3695  //I think it is a bug ion ImageMagick, which reads bitdepth=8 and depth =1 on one machine
3696  //and bitdepth=16 and depth=2 -> Error on the other machine
3697  //\todo fix this error.
3698  /*if(depth==2){
3699  depth=1;
3700  st=ImageBase::ST_unsignedchar;
3701  imst=MagickLib::CharPixel;
3702  }
3703  else */
3704  return -4;
3705  break;
3706  }
3707 
3708  // choose appropriate color model
3709  switch (imcs)
3710  {
3711  case MagickLib::GRAYColorspace:
3712  //cm=ImageBase::CM_Grey;
3713  cm_map="R";
3714  cc=1;
3715  break;
3716 
3717  case MagickLib::RGBColorspace:
3718  case MagickLib::sRGBColorspace:
3719  {
3720  // TODO: or 4, e.g. for RGBA
3721  if (image.channelDepth(MagickLib::AlphaChannel)>1){
3722  //cm=ImageBase::CM_RGBA;
3723  cm_map="RGBA";
3724  cc=4;
3725  } else {
3726  //cm=ImageBase::CM_RGB;
3727  cm_map="RGB";
3728  cc=3;
3729  }
3730  break;
3731  }
3732 
3733  default:
3734  // look in ImageMagick.h for further ColorspaceType's
3735  BIASERR("Color model:"<<imcs<<" not implemented. You may want to add a colorspace/map handler.");
3736  return -3;
3737  break;
3738  }
3739 
3740  // #ifdef BIAS_DEBUG
3741  // COUT("cm_map: "<<cm_map<<endl);
3742  // COUT("MagickLib::Image: Read "<<image.columns()<<"x"<<image.rows()<<" "
3743  // <<image.magick()<<" using ImageMagick++"<<endl);
3744  // COUT("MagickLib::Image: depth "<<image.depth()<<" bit."<<endl );
3745  // COUT("MagickLib::Image: comment "<<endl<<image.comment()<<endl );
3746  // COUT("MagickLib::Image: depth "<<depth<<endl);
3747  // COUT("MagickLib::Image: size "<<width<<"x"<<height<<endl);
3748  // COUT("MagickLib::Image: storage class "<<image.image()->storage_class<<endl);
3749  // COUT("MagickLib::Image: color space "<<image.image()->colorspace<<endl);
3750  // COUT("MagickLib::Image: channel count "<<cc<<endl);
3751  // #endif
3752 
3753  if (!result.IsEmpty()) result.Release(true);
3754 
3755  // do error checking if result has already a specific StorageType
3756  if (result.GetStorageType()!=ImageBase::ST_invalid){
3757  if (result.GetDepth()!=depth){
3758  BIASERR("Error: You tried to load a "<<depth<<" byte "
3759  <<"("<<bitdepth<<"bit) "
3760  <<"image into an image of storage type "
3761  <<result.GetStorageType()<<" which has depth "
3762  <<result.GetDepth()<<" byte.");
3763  result.PrintHeader(cout);
3764  //BIASABORT;
3765  return -2;
3766  }
3767  }
3768 
3769  result.Init(width, height, cc, st, true);
3770  //result.PrintHeader(cout);
3771  result.SetBitDepth(bitdepth);
3772  image.write(0, 0, width, height, cm_map, imst, result.GetImageData());
3773  BIASASSERT(result.GetImageData()!=NULL);
3774  // verbose?
3775  }//end try
3776  catch ( Magick::Exception & error_) {
3777  // be silent about the reason why Magick couldn't load the file.
3778  BIASERR("ImageMagick2BIAS failed."<<endl
3779  <<" Caught Magick exception: "<<endl
3780  <<" "<<error_.what()<<endl );
3781  return -1; // error or unsupported format
3782  }
3783  catch ( std::exception & e) {
3784  BIASERR("ImageMagick2BIAS failed."<<endl
3785  <<" Caught std exception: "<<endl
3786  <<" "<<e.what()<<endl );
3787  return -3;
3788  }
3789  catch (...) {
3790  BIASERR("ImageMagick2BIAS failed."<<endl
3791  <<" Caught unknown exception. "<<endl);
3792  return -4;
3793  }
3794 
3795  return 0; //OK
3796 }
3797 
3798 #endif
3799 
3800 
3801 #ifdef BIAS_HAVE_OPENCV
3802 template <class StorageType>
3803 int ImageConvert::BIAS2ipl(const BIAS::Image<StorageType>& source, IplImage* &dest)
3804 {
3805  //#ifdef USE_MY_OPENCV
3806  //BIASDOUT(D_IMCONV_IPL, "using own CreateIplImage");
3807  // cerr << "using own CreateIplImage\n";
3808  //dest = CreateIplImage(source.GetWidth(), source.GetHeight(),
3809  // sizeof(StorageType) * 8 , source.GetChannelCount());
3810  //#else
3811  //BIASDOUT(D_IMCONV_IPL, "using official CreateIplImage");
3812  //cerr << "using official CreateIplImage\n";
3813  if (source.GetColorModel() == ImageBase::CM_BGRA)
3814  {
3815  dest = cvCreateImage(cvSize(source.GetWidth(), source.GetHeight()),
3816  sizeof(StorageType) * 8, source.GetChannelCount() - 1);
3817  }
3818  else
3819  {
3820  dest = cvCreateImage(cvSize(source.GetWidth(), source.GetHeight()),
3821  sizeof(StorageType) * 8, source.GetChannelCount());
3822  }
3823  //#endif
3824 
3825  StorageType* newImageData = (StorageType*) dest->imageDataOrigin;
3826 
3827  //
3828  // IplImages in OpenCV are always:
3829  // - GREY
3830  // - RGB (with byte Order BGR due to Windows DIB format)
3831  // - RGBA (with byte Order BGRA)
3832  //
3833  // As an limitation of opencv compared to IPL, color images are ALWAYS
3834  // interleaved!
3835 
3836  //cerr << "source.GetColorModel() :"<<source.GetColorModel()<<endl;
3837  switch (source.GetColorModel()) {
3838 
3839  case ImageBase::CM_Grey:
3840  //cerr <<"grey\n";
3841  memcpy(newImageData, source.GetImageData(), source.GetSizeByte() );
3842  break;
3843 
3844  case ImageBase::CM_BGR :
3845  //cerr <<"BGR\n";
3846  if (source.IsPlanar()) {
3847  //cerr <<"Planar\n";
3848  // planar BGR image
3849  for(int channel = 0; channel < 3; channel++) {
3850  register const StorageType* src = source.GetImageData() +
3851  channel*source.GetPixelCount();
3852  register StorageType* act = newImageData + channel;
3853  register const StorageType* stop = src + source.GetPixelCount();
3854  for(;src < stop; src++) {
3855  *act = *src;
3856  act += 3;
3857  }
3858  }
3859  } else {
3860  //cerr <<"Interleaved\n";
3861  // interleaved BGR image - the same format as IplImage itself
3862  memcpy((void*)newImageData, (void*)source.GetImageData(), source.GetSizeByte());
3863  };
3864  break;
3865 
3866  case ImageBase::CM_RGB :
3867  //cerr <<"RGB\n";
3868  if (source.IsPlanar()) {
3869  //cerr <<"Planar\n";
3870  // planar RGB image
3871  for(int channel = 0; channel < 3; channel++) {
3872  register const StorageType* src = source.GetImageData() + (2 - channel) *
3873  source.GetPixelCount(); // RGB instead of BGR order!
3874  register StorageType* act = newImageData + channel;
3875  register const StorageType* stop = src + source.GetPixelCount();
3876  for(;src < stop; src++) {
3877  *act = *src;
3878  act += 3;
3879  }
3880  }
3881  } else {
3882  //cerr <<"Interleaved\n";
3883  // interleaved RGB image
3884  register const StorageType* src = source.GetImageData();
3885  register const StorageType* stop = src + 3 * source.GetPixelCount();
3886  register StorageType* act = newImageData;
3887  while (src < stop) {
3888  // swap RGB because OpenCV uses BGR as native channel order
3889  // only the color conversion routines need this, I fixed highgui to handle channelSeq correctly (jw)
3890  act[0]=src[2];
3891  act[1]=src[1];
3892  act[2]=src[0];
3893  act+=3;
3894  src+=3;
3895  }
3896  }
3897  break;
3898  case ImageBase::CM_BGRA:
3899  { // drop alpha channel
3900  const StorageType *b = source.GetImageData();
3901  StorageType *d = newImageData;
3902  const int size = source.GetPixelCount();
3903  if (source.IsPlanar())
3904  {
3905  const StorageType *g = b + size, *r = g + size;
3906  for (int i = 0; i < size; i++)
3907  {
3908  *d = *b;
3909  d++;
3910  b++;
3911  *d = *g;
3912  d++;
3913  g++;
3914  *d = *r;
3915  d++;
3916  r++;
3917  }
3918  }
3919  else
3920  {
3921  for (int i = 0; i < size; i++)
3922  {
3923  *d = *b;
3924  d++;
3925  b++;
3926  *d = *b;
3927  d++;
3928  b++;
3929  *d = *b;
3930  d++;
3931  b += 2;
3932  }
3933  }
3934  }
3935  break;
3936  default:
3937  BIASERR("Only Grey, BGR and RGB images can be converted to IplImages yet."
3938  <<" Aborting!");
3939  return -1;
3940  }
3941 
3942  return 0;
3943 }
3944 
3945 template <class StorageType>
3946 int ImageConvert::Ipl2BIAS(IplImage* source, BIAS::Image<StorageType>& dest)
3947 {
3948  // Does the color depth match?
3949  if (8*sizeof(StorageType) != source->depth) {
3950  BIASERR("Cannot convert an IplImage into an Image of different color "
3951  <<"depth!");
3952  return -1;
3953  }
3954 
3955  if (source->width <=0 || source->height <= 0) {
3956  BIASERR("IplImage to be converted to Image has no size!");
3957  return -1;
3958  }
3959  if ( !dest.IsEmpty() )
3960  dest.Release();
3961  // What kind of image do we have?
3962  switch (source->nChannels) {
3963  case 1: // gray image
3964  // Release the old image data and allocate new memory
3965  dest.Init(source->width, source->height, 1);
3966  memcpy(dest.GetImageData(), source->imageDataOrigin, dest.GetSizeByte());
3967  break;
3968  case 3:
3969  if (strcmp(source->colorModel, "RGB")==0 &&
3970  strcmp(source->channelSeq, "BGR")==0 &&
3971  source->dataOrder==IPL_DATA_ORDER_PIXEL &&
3972  (source->depth>>3)==sizeof(StorageType) ){
3973  dest.Init(source->width, source->height, 3);
3974  register unsigned char* src = (unsigned char*) source->imageDataOrigin;
3975  register unsigned char* stop = src + 3 * source->width * source->height;
3976  register StorageType* dst = dest.GetImageData();
3977  while (src < stop) {
3978  dst[0]=src[2];
3979  dst[1]=src[1];
3980  dst[2]=src[0];
3981  dst+=3; src+=3;
3982  }
3983  } else {
3984  BIASERR("Ipl2BIAS not implemented for this color model or inavlid storage type");
3985  return -1;
3986  }
3987  break;
3988  default:
3989  BIASERR("Only gray IplImages can be converted to Images yet!");
3990  return -1;
3991  }
3992  return 0;
3993 }
3994 #endif // BIAS_HAVE_OPENCV
3995 
3996 
3997 
3998 int ImageConvert::DeinterleaveHorizontal(const BIAS::ImageBase & raw,
3999  BIAS::ImageBase & out)
4000 {
4001  if (raw.GetColorModel()!= vidap_DEFAULT_PACKED_COLORMODEL)
4002  return -1;
4003  if (raw.GetChannelCount()!= 3)
4004  return -2;
4005  if ( ImageBase::GetSizeByte(raw.GetStorageType()) != 1 ){
4006  BIASERR("storagetypes size must be 1 for now due to simple pointer arithmetics.\n"
4007  "Other pointer sizes need to be implemented.");
4008  return -3;
4009  }
4010  if (raw.GetStorageType()!= out.GetStorageType()){
4011  BIASERR("storagetypes must match");
4012  return -4;
4013  }
4014 
4015  BIASASSERT(raw.GetColorModel()== vidap_DEFAULT_PACKED_COLORMODEL );
4016  BIASASSERT(raw.GetChannelCount()== 3);
4017  BIASASSERT(ImageBase::GetSizeByte(raw.GetStorageType()) == 1);
4018 
4019  // check if we need re-allocation
4020  if (!out.IsEmpty())
4021  out.Release();
4022 
4023  // triple width for appeding 3 camera images horizontally
4024  out.Init( 3* raw.GetWidth(), raw.GetHeight(), 1 );
4025  out.SetColorModel( vidap_DEFAULT_BAYER_COLORMODEL );
4026 
4027  // abcABC --> aAbBcC
4028  unsigned char *s =NULL, *d0=NULL, *d1=NULL, *d2=NULL;
4029 
4030  for (unsigned int y=0; y<raw.GetHeight(); y++){
4031  s = (unsigned char*)raw.GetImageDataArray()[y];
4032  d0 = (unsigned char*)out.GetImageDataArray()[y];
4033  d1 = (unsigned char*)out.GetImageDataArray()[y] + raw.GetWidth();
4034  d2 = (unsigned char*)out.GetImageDataArray()[y] + 2*raw.GetWidth();
4035  for (unsigned int x=0; x<raw.GetWidth(); x++){
4036  *d0 = *s; s++; d0++;
4037  *d1 = *s; s++; d1++;
4038  *d2 = *s; s++; d2++;
4039  }
4040  }
4041 
4042  return 0;
4043 }
4044 /*
4045 template <class StorageType>
4046 int BIAS::ImageConvert::BayerToRGBPGR_(const Image<StorageType>& source,
4047  Image<StorageType>& dest )
4048 {
4049  StorageType *sink = dest.GetImageData() ;
4050  const StorageType *src = source.GetImageData() ;
4051 
4052  unsigned int width= source.GetWidth();
4053  unsigned int srcheight=source.GetHeight() -1;
4054  unsigned int xoffset = 0, yoffset = 1;
4055 
4056  // first pixel in first line
4057  StorageType G = *src;
4058  StorageType R = *(src+width);
4059  StorageType B = *(src+1);
4060 
4061  sink[0]=0; sink[1]=0; sink[2]=0;
4062  sink+=3; src++;
4063  // first line
4064  if (0 == yoffset) {
4065  for (unsigned int x=1; x<width-1; x++){
4066  if (x%2 == xoffset) { // staying on Red
4067  R = *src;
4068  G = ( *(src+-1)+ *(src+1) + *(src+ width) ) /3;
4069  B = ( *(src+(width -1)) + *(src+(width +1))) /2;
4070  }
4071  else { // staying on Green
4072  R = ( *(src+-1) + *(src+1) ) /2;
4073  G = *src;
4074  B = (*(src+width) ) ;
4075  }
4076  *sink++ =R;
4077  *sink++ =G;
4078  *sink++ =B;
4079  src++;
4080  }
4081  }
4082  else {
4083  for (unsigned int x=1; x<width-1; x++){
4084  if (x%2 == xoffset) { // staying on Green
4085  R = ( *(src+width) ) ;
4086  G = *src;
4087  B = ( *(src+(-1)) + *(src+1) ) /2;
4088  }
4089  else { // staying on Blue
4090  R = ( *(src+(width -1)) + *(src+(width +1))) /2;
4091  G = ( *(src-1) + *(src+1) + *(src+width) ) /3;
4092  B = *src;
4093  }
4094  *sink++ =R;
4095  *sink++ =G;
4096  *sink++ =B;
4097  src++;
4098  }
4099  }
4100  // last pixel in first line
4101  if (0 == yoffset) {
4102  if ((width-1)%2 == xoffset) { // staying on Red
4103  R = *src;
4104  G = ( *(src+(-1))+ *(src+(+ width)) ) /2;
4105  B = *(src+(width -1)) ;
4106  }
4107  else { // staying on Green
4108  R = *(src+(-1));
4109  G = *src;
4110  B = (*(src+(+ width)) ) ;
4111  }
4112  }
4113  else {
4114  if ((width-1)%2 == xoffset) { // staying on Green
4115  R = ( *(src+(+ width)) ) ;
4116  G = *src;
4117  B = *(src+(-1)) ;
4118  }
4119  else { // staying on Blue
4120  R = *(src+(width -1));
4121  G = ( *(src+(-1)) + *(src+(+ width)) ) /2;
4122  B = *src;
4123  }
4124  }
4125  *sink++ =R;
4126  *sink++ =G;
4127  *sink++ =B;
4128  src++;
4129 
4130 
4131  //loop
4132  for (unsigned int y=1; y<srcheight; y++) {
4133  // first pixel in line
4134  if (y%2 == yoffset)
4135  if (0%2 == xoffset) { // staying on Red
4136  R = *src;
4137  G = (*(src - width ) + *(src+1) + *(src+width) ) /3;
4138  B = ( *(src - width -1) + *(src+(width +1))) /2;
4139  } else { // staying on Green
4140  R = *(src+1);
4141  G = *src;
4142  B = ( *(src - width ) + *(src+ width ) ) /2;
4143  }
4144  else
4145  if (0 == xoffset) { // staying on Green
4146  R = ( *(src - width ) + *(src+ width ) ) /2;
4147  G = *src;
4148  B = *(src+1);
4149  }
4150  else { // staying on Blue
4151  R = ( *(src - width +1) + *(src+(width +1))) /2;
4152  G = (*(src - width ) + *(src+(+1)) + *(src+(+ width)) ) /3;
4153  B = *src;
4154  }
4155  *sink++ =R;
4156  *sink++ =G;
4157  *sink++ =B;
4158  src++;
4159 
4160  // main part of line
4161  for (unsigned int x=1; x<width-1; x++) {
4162  if (y%2 == yoffset)
4163  if (x%2 == xoffset) { // staying on Red
4164  R = *src;
4165  G = (*(src - width ) + *(src -1 )
4166  + *(src+(+1)) + *(src+ (+ width)) ) /4;
4167  B = ( *(src - width +1 ) + *(src - width -1 )
4168  + *(src+(width -1)) + *(src+(width +1))) /4;
4169  } else { // staying on Green
4170  R = ( *(src -1 ) + *(src+ 1 ) ) /2;
4171  G = *src;
4172  B = ( *(src - width ) + *(src+ width ) ) /2;
4173  }
4174  else
4175 
4176  if (x%2 == xoffset) { // staying on Green
4177  R = ( *(src - width ) + *(src+ width ) ) /2;
4178  G = *src;
4179  B = ( *(src+(-1)) + *(src+(+1)) ) /2;
4180  }
4181  else { // staying on Blue
4182  R = ( *(src - width +1 ) + *(src - width -1 )
4183  + *(src+(width -1)) + *(src+(width +1))) /4;
4184  G = (*(src - width ) + *(src -1 )
4185  + *(src+(+1)) + *(src+(+ width)) ) /4;
4186  B = *src;
4187  }
4188  *sink++ =R;
4189  *sink++ =G;
4190  *sink++ =B;
4191  src++;
4192  }
4193 
4194  // last pixel in line
4195  if (y%2 == yoffset)
4196  if ((width-1)%2 == xoffset) { // staying on Red
4197  R = *src;
4198  G = (*(src - width ) + *(src -1 ) + *(src+ width ) ) /3;
4199  B = ( *(src - width +1 ) + *(src+(width -1))) /2;
4200  } else { // staying on Green
4201  R = *(src -1 ) ;
4202  G = *src;
4203  B = ( *(src - width ) + *(src+ width ) ) /2;
4204  }
4205  else
4206  if ((width-1)%2 == xoffset) { // staying on Green
4207  R = ( *(src - width ) + *(src+ width ) ) /2;
4208  G = *src;
4209  B = *(src -1 );
4210  }
4211  else {
4212 
4213 
4214  // staying on Blue
4215  R = ( *(src - width +1 ) + *(src+(width -1))) /2;
4216  G = (*(src - width ) + *(src -1 )+ *(src+( width)) ) /3;
4217  B = *src;
4218  }
4219  *sink++ =R;
4220  *sink++ =G;
4221  *sink++ =B;
4222  src++;
4223 
4224 
4225  }
4226 
4227  // first pixel in last line
4228  if ((srcheight)%2 == yoffset) {
4229  if (0 == xoffset) { // staying on Red
4230  R = *src;
4231  G = ( *(src - width )+ *(src +1 ) ) /2;
4232  B = *(src - width -1 ) ;
4233  }
4234  else { // staying on Green
4235  R = *(src +1 );
4236  G = *src;
4237  B = (*(src - width ) ) ;
4238  }
4239  }
4240  else {
4241  if (0 == xoffset) { // staying on Green
4242  R = ( *(src - width ) ) ;
4243  G = *src;
4244  B = *(src+ 1 ) ;
4245  }
4246  else { // staying on Blue
4247  R = *(src - width -1 );
4248  G = ( *(src - width ) + *(src +1 ) ) /2;
4249  B = *src;
4250  }
4251  }
4252  *sink++ =R;
4253  *sink++ =G;
4254  *sink++ =B;
4255  src++;
4256  // last line
4257 
4258  if ((srcheight)%2 == yoffset) {
4259  for (unsigned int x=1; x<width-1; x++){
4260  if (x%2 == xoffset) { // staying on Red
4261  R = *src;
4262  G = ( *(src -1 )+ *(src - width ) + *(src +1 ) ) /3;
4263  B = ( *(src - width +1 ) + *(src - width -1 )) /2;
4264  }
4265  else { // staying on Green
4266  R = ( *(src -1 ) + *(src+ 1 ) ) /2;
4267  G = *src;
4268  B = (*(src - width ) ) ;
4269  }
4270  *sink++ =R;
4271  *sink++ =G;
4272  *sink++ =B;
4273  src++;
4274  }
4275  }
4276  else {
4277  for (unsigned int x=1; x<width-1; x++){
4278  if (x%2 == xoffset) { // staying on Green
4279  R = ( *(src - width ) ) ;
4280  G = *src;
4281  B = ( *(src -1 ) + *(src +1 ) ) /2;
4282  }
4283  else { // staying on Blue
4284  R = ( *(src - width +1 ) + *(src - width -1 )) /2;
4285  G = ( *(src - width ) + *(src -1 ) + *(src +1 ) ) /3;
4286  B = *src;
4287  }
4288  *sink++ =R;
4289  *sink++ =G;
4290  *sink++ =B;
4291  src++;
4292  }
4293  }
4294  // last pixel in last line
4295  if ((srcheight-1)%2 == yoffset) {
4296  if ((width-1)%2 == xoffset) { // staying on Red
4297  R = *src;
4298  G = ( *(src -1 )+ *(src - width ) ) /2;
4299  B = *(src - width +1 ) ;
4300  }
4301  else { // staying on Green
4302  R = *(src -1 );
4303  G = *src;
4304  B = (*(src - width ) ) ;
4305  }
4306  }
4307  else {
4308  if ((width-1)%2 == xoffset) { // staying on Green
4309  R = ( *(src - width ) ) ;
4310  G = *src;
4311  B = *(src+(-1)) ;
4312  }
4313  else { // staying on Blue
4314  R = *(src - width +1 );
4315  G = ( *(src -1 ) + *(src - width) ) /2;
4316  B = *src;
4317  }
4318  }
4319  *sink++ =R;
4320  *sink++ =G;
4321  *sink++ =B;
4322  src++;
4323 
4324  return 0;
4325 }
4326 */
4327 template<class StorageType>
4328 int ImageConvert::BayerToRGBSimple(const StorageType* source, StorageType* dest,
4329  int sx, int sy, ImageBase::EColorModel tile){
4330 return BayerToRGBSimple_( source, dest, sx, sy, tile);
4331 
4332 }
4333 
4334 template<class StorageType>
4335 int ImageConvert::BayerToRGBSimple_(const StorageType* source, StorageType* dest,
4336  int sx, int sy, ImageBase::EColorModel tile){
4337 
4338  const int bayerStep = sx;
4339  const int rgbStep = 3 * sx;
4340  int width = sx;
4341  int height = sy;
4342  int blue = tile == ImageBase::CM_Bayer_BGGR
4343  || tile == ImageBase::CM_Bayer_GBRG ? -1 : 1;
4344  int start_with_green = tile == ImageBase::CM_Bayer_GBRG
4345  || tile == ImageBase::CM_Bayer_GRBG;
4346  int i, imax, iinc;
4347 
4348  // add black border
4349  imax = sx * sy * 3;
4350  for (i = sx * (sy - 1) * 3; i < imax; i++) {
4351  dest[i] = 0;
4352  }
4353  iinc = (sx - 1) * 3;
4354  for (i = (sx - 1) * 3; i < imax; i += iinc) {
4355  dest[i++] = 0;
4356  dest[i++] = 0;
4357  dest[i++] = 0;
4358  }
4359 
4360  dest += 1;
4361  width -= 1;
4362  height -= 1;
4363 
4364  for (; height--; source += bayerStep, dest += rgbStep) {
4365  const StorageType *bayerEnd = source + width;
4366 
4367  if (start_with_green) {
4368  dest[-blue] = source[1];
4369  dest[0] = (source[0] + source[bayerStep + 1] + 1) >> 1;
4370  dest[blue] = source[bayerStep];
4371  source++;
4372  dest += 3;
4373  }
4374 
4375  if (blue > 0) {
4376  for (; source <= bayerEnd - 2; source += 2, dest += 6) {
4377  dest[-1] = source[0];
4378  dest[0] = (source[1] + source[bayerStep] + 1) >> 1;
4379  dest[1] = source[bayerStep + 1];
4380 
4381  dest[2] = source[2];
4382  dest[3] = (source[1] + source[bayerStep + 2] + 1) >> 1;
4383  dest[4] = source[bayerStep + 1];
4384  }
4385  } else {
4386  for (; source <= bayerEnd - 2; source += 2, dest += 6) {
4387  dest[1] = source[0];
4388  dest[0] = (source[1] + source[bayerStep] + 1) >> 1;
4389  dest[-1] = source[bayerStep + 1];
4390 
4391  dest[4] = source[2];
4392  dest[3] = (source[1] + source[bayerStep + 2] + 1) >> 1;
4393  dest[2] = source[bayerStep + 1];
4394  }
4395  }
4396 
4397  if (source < bayerEnd) {
4398  dest[-blue] = source[0];
4399  dest[0] = (source[1] + source[bayerStep] + 1) >> 1;
4400  dest[blue] = source[bayerStep + 1];
4401  source++;
4402  dest += 3;
4403  }
4404 
4405  source -= width;
4406  dest -= width * 3;
4407 
4408  blue = -blue;
4409  start_with_green = !start_with_green;
4410  }
4411 
4412  return 0;
4413 }
4414 
4415 template<class StorageType>
4416 int ImageConvert::BayerToRGBBilinear_(const StorageType* bayer, StorageType* rgb,
4417  int sx, int sy, ImageBase::EColorModel tile){
4418 
4419  const int bayerStep = sx;
4420  const int rgbStep = 3 * sx;
4421  int width = sx;
4422  int height = sy;
4423  int blue = tile == ImageBase::CM_Bayer_BGGR
4424  || tile == ImageBase::CM_Bayer_GBRG ? -1 : 1;
4425  int start_with_green = tile == ImageBase::CM_Bayer_GBRG
4426  || tile == ImageBase::CM_Bayer_GRBG;
4427 
4428 
4429 ClearBorders_(rgb, sx, sy, 1);
4430  rgb += rgbStep + 3 + 1;
4431  height -= 2;
4432  width -= 2;
4433 
4434  for (; height--; bayer += bayerStep, rgb += rgbStep) {
4435  int t0, t1;
4436  const StorageType *bayerEnd = bayer + width;
4437 
4438  if (start_with_green) {
4439  /* OpenCV has a bug in the next line, which was
4440  t0 = (bayer[0] + bayer[bayerStep * 2] + 1) >> 1; */
4441  t0 = (bayer[1] + bayer[bayerStep * 2 + 1] + 1) >> 1;
4442  t1 = (bayer[bayerStep] + bayer[bayerStep + 2] + 1) >> 1;
4443  rgb[-blue] = (StorageType) t0;
4444  rgb[0] = bayer[bayerStep + 1];
4445  rgb[blue] = (StorageType) t1;
4446  bayer++;
4447  rgb += 3;
4448  }
4449 
4450  if (blue > 0) {
4451  for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
4452  t0 = (bayer[0] + bayer[2] + bayer[bayerStep * 2] +
4453  bayer[bayerStep * 2 + 2] + 2) >> 2;
4454  t1 = (bayer[1] + bayer[bayerStep] +
4455  bayer[bayerStep + 2] + bayer[bayerStep * 2 + 1] +
4456  2) >> 2;
4457  rgb[-1] = (StorageType) t0;
4458  rgb[0] = (StorageType) t1;
4459  rgb[1] = bayer[bayerStep + 1];
4460 
4461  t0 = (bayer[2] + bayer[bayerStep * 2 + 2] + 1) >> 1;
4462  t1 = (bayer[bayerStep + 1] + bayer[bayerStep + 3] +
4463  1) >> 1;
4464  rgb[2] = (StorageType) t0;
4465  rgb[3] = bayer[bayerStep + 2];
4466  rgb[4] = (StorageType) t1;
4467  }
4468  } else {
4469  for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
4470  t0 = (bayer[0] + bayer[2] + bayer[bayerStep * 2] +
4471  bayer[bayerStep * 2 + 2] + 2) >> 2;
4472  t1 = (bayer[1] + bayer[bayerStep] +
4473  bayer[bayerStep + 2] + bayer[bayerStep * 2 + 1] +
4474  2) >> 2;
4475  rgb[1] = (StorageType) t0;
4476  rgb[0] = (StorageType) t1;
4477  rgb[-1] = bayer[bayerStep + 1];
4478 
4479  t0 = (bayer[2] + bayer[bayerStep * 2 + 2] + 1) >> 1;
4480  t1 = (bayer[bayerStep + 1] + bayer[bayerStep + 3] +
4481  1) >> 1;
4482  rgb[4] = (StorageType) t0;
4483  rgb[3] = bayer[bayerStep + 2];
4484  rgb[2] = (StorageType) t1;
4485  }
4486  }
4487 
4488  if (bayer < bayerEnd) {
4489  t0 = (bayer[0] + bayer[2] + bayer[bayerStep * 2] +
4490  bayer[bayerStep * 2 + 2] + 2) >> 2;
4491  t1 = (bayer[1] + bayer[bayerStep] +
4492  bayer[bayerStep + 2] + bayer[bayerStep * 2 + 1] +
4493  2) >> 2;
4494  rgb[-blue] = (StorageType) t0;
4495  rgb[0] = (StorageType) t1;
4496  rgb[blue] = bayer[bayerStep + 1];
4497  bayer++;
4498  rgb += 3;
4499  }
4500 
4501  bayer -= width;
4502  rgb -= width * 3;
4503 
4504  blue = -blue;
4505  start_with_green = !start_with_green;
4506  }
4507  return 0;
4508 }
4509 
4510 template<class StorageType>
4511 int ImageConvert::BayerToRGBNearestNeighbour_(const StorageType* bayer, StorageType* rgb,
4512  int sx, int sy, ImageBase::EColorModel tile){
4513 
4514  const int bayerStep = sx;
4515  const int rgbStep = 3 * sx;
4516  int width = sx;
4517  int height = sy;
4518  int blue = tile == ImageBase::CM_Bayer_BGGR
4519  || tile == ImageBase::CM_Bayer_GBRG ? -1 : 1;
4520  int start_with_green = tile == ImageBase::CM_Bayer_GBRG
4521  || tile == ImageBase::CM_Bayer_GRBG;
4522  int i, imax, iinc;
4523 
4524  imax = sx * sy * 3;
4525  for (i = sx * (sy - 1) * 3; i < imax; i++) {
4526  rgb[i] = 0;
4527  }
4528  iinc = (sx - 1) * 3;
4529  for (i = (sx - 1) * 3; i < imax; i += iinc) {
4530  rgb[i++] = 0;
4531  rgb[i++] = 0;
4532  rgb[i++] = 0;
4533  }
4534 
4535  rgb += 1;
4536  width -= 1;
4537  height -= 1;
4538 
4539  for (; height--; bayer += bayerStep, rgb += rgbStep) {
4540  //int t0, t1;
4541  const StorageType *bayerEnd = bayer + width;
4542 
4543  if (start_with_green) {
4544  rgb[-blue] = bayer[1];
4545  rgb[0] = bayer[bayerStep + 1];
4546  rgb[blue] = bayer[bayerStep];
4547  bayer++;
4548  rgb += 3;
4549  }
4550 
4551  if (blue > 0) {
4552  for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
4553  rgb[-1] = bayer[0];
4554  rgb[0] = bayer[1];
4555  rgb[1] = bayer[bayerStep + 1];
4556 
4557  rgb[2] = bayer[2];
4558  rgb[3] = bayer[bayerStep + 2];
4559  rgb[4] = bayer[bayerStep + 1];
4560  }
4561  } else {
4562  for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
4563  rgb[1] = bayer[0];
4564  rgb[0] = bayer[1];
4565  rgb[-1] = bayer[bayerStep + 1];
4566 
4567  rgb[4] = bayer[2];
4568  rgb[3] = bayer[bayerStep + 2];
4569  rgb[2] = bayer[bayerStep + 1];
4570  }
4571  }
4572 
4573  if (bayer < bayerEnd) {
4574  rgb[-blue] = bayer[0];
4575  rgb[0] = bayer[1];
4576  rgb[blue] = bayer[bayerStep + 1];
4577  bayer++;
4578  rgb += 3;
4579  }
4580 
4581  bayer -= width;
4582  rgb -= width * 3;
4583 
4584  blue = -blue;
4585  start_with_green = !start_with_green;
4586  }
4587  return 0;
4588 }
4589 
4590 template<class StorageType>
4591 void ImageConvert::ClearBorders_(StorageType *rgb, int sx, int sy, int w)
4592 {
4593  int i, j;
4594  // black edges are added with a width w:
4595  i = 3 * sx * w - 1;
4596  j = 3 * sx * sy - 1;
4597  while (i >= 0) {
4598  rgb[i--] = 0;
4599  rgb[j--] = 0;
4600  }
4601 
4602  int low = sx * (w - 1) * 3 - 1 + w * 3;
4603  i = low + sx * (sy - w * 2 + 1) * 3;
4604  while (i > low) {
4605  j = 6 * w;
4606  while (j > 0) {
4607  rgb[i--] = 0;
4608  j--;
4609  }
4610  i -= (sx - 2 * w) * 3;
4611  }
4612 }
4613 
4614 int ImageConvert::BayerToRGBHQLinear_(const unsigned char* bayer, unsigned char* rgb, int sx, int sy, ImageBase::EColorModel tile){
4615 
4616  const int bayerStep = sx;
4617  const int rgbStep = 3 * sx;
4618  int width = sx;
4619  int height = sy;
4620  int blue = tile == ImageBase::CM_Bayer_BGGR
4621  || tile == ImageBase::CM_Bayer_GBRG ? -1 : 1;
4622  int start_with_green = tile == ImageBase::CM_Bayer_GBRG
4623  || tile == ImageBase::CM_Bayer_GRBG;
4624 
4625 
4626  ClearBorders_<unsigned char>(rgb, sx, sy, 2);
4627  rgb += 2 * rgbStep + 6 + 1;
4628  height -= 4;
4629  width -= 4;
4630 
4631  /* We begin with a (+1 line,+1 column) offset with respect to bilinear decoding, so start_with_green is the same, but blue is opposite */
4632  blue = -blue;
4633 
4634  for (; height--; bayer += bayerStep, rgb += rgbStep) {
4635  int t0, t1;
4636  const unsigned char *bayerEnd = bayer + width;
4637  const int bayerStep2 = bayerStep * 2;
4638  const int bayerStep3 = bayerStep * 3;
4639  const int bayerStep4 = bayerStep * 4;
4640 
4641  if (start_with_green) {
4642  /* at green pixel */
4643  rgb[0] = bayer[bayerStep2 + 2];
4644  t0 = rgb[0] * 5
4645  + ((bayer[bayerStep + 2] + bayer[bayerStep3 + 2]) << 2)
4646  - bayer[2]
4647  - bayer[bayerStep + 1]
4648  - bayer[bayerStep + 3]
4649  - bayer[bayerStep3 + 1]
4650  - bayer[bayerStep3 + 3]
4651  - bayer[bayerStep4 + 2]
4652  + ((bayer[bayerStep2] + bayer[bayerStep2 + 4] + 1) >> 1);
4653  t1 = rgb[0] * 5 +
4654  ((bayer[bayerStep2 + 1] + bayer[bayerStep2 + 3]) << 2)
4655  - bayer[bayerStep2]
4656  - bayer[bayerStep + 1]
4657  - bayer[bayerStep + 3]
4658  - bayer[bayerStep3 + 1]
4659  - bayer[bayerStep3 + 3]
4660  - bayer[bayerStep2 + 4]
4661  + ((bayer[2] + bayer[bayerStep4 + 2] + 1) >> 1);
4662  t0 = (t0 + 4) >> 3;
4663  CLIP<unsigned char>((unsigned char&)t0, rgb[-blue]);
4664  t1 = (t1 + 4) >> 3;
4665  CLIP<unsigned char>((unsigned char&)t1, rgb[blue]);
4666 
4667  bayer++;
4668  rgb += 3;
4669  }
4670 
4671  if (blue > 0) {
4672  for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
4673  /* B at B */
4674  rgb[1] = bayer[bayerStep2 + 2];
4675  /* R at B */
4676  t0 = ((bayer[bayerStep + 1] + bayer[bayerStep + 3] +
4677  bayer[bayerStep3 + 1] + bayer[bayerStep3 + 3]) << 1)
4678  -
4679  (((bayer[2] + bayer[bayerStep2] +
4680  bayer[bayerStep2 + 4] + bayer[bayerStep4 +
4681  2]) * 3 + 1) >> 1)
4682  + rgb[1] * 6;
4683  /* G at B */
4684  t1 = ((bayer[bayerStep + 2] + bayer[bayerStep2 + 1] +
4685  bayer[bayerStep2 + 3] + bayer[bayerStep3 + 2]) << 1)
4686  - (bayer[2] + bayer[bayerStep2] +
4687  bayer[bayerStep2 + 4] + bayer[bayerStep4 + 2])
4688  + (rgb[1] << 2);
4689  t0 = (t0 + 4) >> 3;
4690  CLIP<unsigned char>((unsigned char&)t0, rgb[-1]);
4691  t1 = (t1 + 4) >> 3;
4692  CLIP<unsigned char>((unsigned char&)t1, rgb[0]);
4693  /* at green pixel */
4694  rgb[3] = bayer[bayerStep2 + 3];
4695  t0 = rgb[3] * 5
4696  + ((bayer[bayerStep + 3] + bayer[bayerStep3 + 3]) << 2)
4697  - bayer[3]
4698  - bayer[bayerStep + 2]
4699  - bayer[bayerStep + 4]
4700  - bayer[bayerStep3 + 2]
4701  - bayer[bayerStep3 + 4]
4702  - bayer[bayerStep4 + 3]
4703  +
4704  ((bayer[bayerStep2 + 1] + bayer[bayerStep2 + 5] +
4705  1) >> 1);
4706  t1 = rgb[3] * 5 +
4707  ((bayer[bayerStep2 + 2] + bayer[bayerStep2 + 4]) << 2)
4708  - bayer[bayerStep2 + 1]
4709  - bayer[bayerStep + 2]
4710  - bayer[bayerStep + 4]
4711  - bayer[bayerStep3 + 2]
4712  - bayer[bayerStep3 + 4]
4713  - bayer[bayerStep2 + 5]
4714  + ((bayer[3] + bayer[bayerStep4 + 3] + 1) >> 1);
4715  t0 = (t0 + 4) >> 3;
4716  CLIP<unsigned char>((unsigned char&)t0, rgb[2]);
4717  t1 = (t1 + 4) >> 3;
4718  CLIP<unsigned char>((unsigned char&)t1, rgb[4]);
4719  }
4720  } else {
4721  for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
4722  /* R at R */
4723  rgb[-1] = bayer[bayerStep2 + 2];
4724  /* B at R */
4725  t0 = ((bayer[bayerStep + 1] + bayer[bayerStep + 3] +
4726  bayer[bayerStep3 + 1] + bayer[bayerStep3 + 3]) << 1)
4727  -
4728  (((bayer[2] + bayer[bayerStep2] +
4729  bayer[bayerStep2 + 4] + bayer[bayerStep4 +
4730  2]) * 3 + 1) >> 1)
4731  + rgb[-1] * 6;
4732  /* G at R */
4733  t1 = ((bayer[bayerStep + 2] + bayer[bayerStep2 + 1] +
4734  bayer[bayerStep2 + 3] + bayer[bayerStep * 3 +
4735  2]) << 1)
4736  - (bayer[2] + bayer[bayerStep2] +
4737  bayer[bayerStep2 + 4] + bayer[bayerStep4 + 2])
4738  + (rgb[-1] << 2);
4739  t0 = (t0 + 4) >> 3;
4740  CLIP<unsigned char>((unsigned char&)t0, rgb[1]);
4741  t1 = (t1 + 4) >> 3;
4742  CLIP<unsigned char>((unsigned char&)t1, rgb[0]);
4743 
4744  /* at green pixel */
4745  rgb[3] = bayer[bayerStep2 + 3];
4746  t0 = rgb[3] * 5
4747  + ((bayer[bayerStep + 3] + bayer[bayerStep3 + 3]) << 2)
4748  - bayer[3]
4749  - bayer[bayerStep + 2]
4750  - bayer[bayerStep + 4]
4751  - bayer[bayerStep3 + 2]
4752  - bayer[bayerStep3 + 4]
4753  - bayer[bayerStep4 + 3]
4754  +
4755  ((bayer[bayerStep2 + 1] + bayer[bayerStep2 + 5] +
4756  1) >> 1);
4757  t1 = rgb[3] * 5 +
4758  ((bayer[bayerStep2 + 2] + bayer[bayerStep2 + 4]) << 2)
4759  - bayer[bayerStep2 + 1]
4760  - bayer[bayerStep + 2]
4761  - bayer[bayerStep + 4]
4762  - bayer[bayerStep3 + 2]
4763  - bayer[bayerStep3 + 4]
4764  - bayer[bayerStep2 + 5]
4765  + ((bayer[3] + bayer[bayerStep4 + 3] + 1) >> 1);
4766  t0 = (t0 + 4) >> 3;
4767  CLIP<unsigned char>((unsigned char&)t0, rgb[4]);
4768  t1 = (t1 + 4) >> 3;
4769  CLIP<unsigned char>((unsigned char&)t1, rgb[2]);
4770  }
4771  }
4772 
4773  if (bayer < bayerEnd) {
4774  /* B at B */
4775  rgb[blue] = bayer[bayerStep2 + 2];
4776  /* R at B */
4777  t0 = ((bayer[bayerStep + 1] + bayer[bayerStep + 3] +
4778  bayer[bayerStep3 + 1] + bayer[bayerStep3 + 3]) << 1)
4779  -
4780  (((bayer[2] + bayer[bayerStep2] +
4781  bayer[bayerStep2 + 4] + bayer[bayerStep4 +
4782  2]) * 3 + 1) >> 1)
4783  + rgb[blue] * 6;
4784  /* G at B */
4785  t1 = (((bayer[bayerStep + 2] + bayer[bayerStep2 + 1] +
4786  bayer[bayerStep2 + 3] + bayer[bayerStep3 + 2])) << 1)
4787  - (bayer[2] + bayer[bayerStep2] +
4788  bayer[bayerStep2 + 4] + bayer[bayerStep4 + 2])
4789  + (rgb[blue] << 2);
4790  t0 = (t0 + 4) >> 3;
4791  CLIP<unsigned char>((unsigned char&)t0, rgb[-blue]);
4792  t1 = (t1 + 4) >> 3;
4793  CLIP<unsigned char>((unsigned char&)t1, rgb[0]);
4794 
4795  bayer++;
4796  rgb += 3;
4797  }
4798 
4799 
4800  bayer -= width;
4801  rgb -= width * 3;
4802 
4803  blue = -blue;
4804  start_with_green = !start_with_green;
4805  }
4806 
4807 
4808  return 0;
4809 }
4810 
4811 int ImageConvert::BayerToRGBHQLinear_(const unsigned short* bayer, unsigned short* rgb, int sx, int sy, ImageBase::EColorModel tile, int bit){
4812 
4813  unsigned short bits = (unsigned short) bit;
4814  const int bayerStep = sx;
4815  const int rgbStep = 3 * sx;
4816  int width = sx;
4817  int height = sy;
4818  int blue = tile == ImageBase::CM_Bayer_BGGR
4819  || tile == ImageBase::CM_Bayer_GBRG ? -1 : 1;
4820  int start_with_green = tile == ImageBase::CM_Bayer_GBRG
4821  || tile == ImageBase::CM_Bayer_GRBG;
4822 
4823 
4824  ClearBorders_<unsigned short>(rgb, sx, sy, 2);
4825  rgb += 2 * rgbStep + 6 + 1;
4826  height -= 4;
4827  width -= 4;
4828 
4829  /* We begin with a (+1 line,+1 column) offset with respect to bilinear decoding, so start_with_green is the same, but blue is opposite */
4830  blue = -blue;
4831 
4832  for (; height--; bayer += bayerStep, rgb += rgbStep) {
4833  unsigned short t0, t1;
4834  const unsigned short *bayerEnd = bayer + width;
4835  const int bayerStep2 = bayerStep * 2;
4836  const int bayerStep3 = bayerStep * 3;
4837  const int bayerStep4 = bayerStep * 4;
4838 
4839  if (start_with_green) {
4840  /* at green pixel */
4841  rgb[0] = bayer[bayerStep2 + 2];
4842  t0 = rgb[0] * 5
4843  + ((bayer[bayerStep + 2] + bayer[bayerStep3 + 2]) << 2)
4844  - bayer[2]
4845  - bayer[bayerStep + 1]
4846  - bayer[bayerStep + 3]
4847  - bayer[bayerStep3 + 1]
4848  - bayer[bayerStep3 + 3]
4849  - bayer[bayerStep4 + 2]
4850  + ((bayer[bayerStep2] + bayer[bayerStep2 + 4] + 1) >> 1);
4851  t1 = rgb[0] * 5 +
4852  ((bayer[bayerStep2 + 1] + bayer[bayerStep2 + 3]) << 2)
4853  - bayer[bayerStep2]
4854  - bayer[bayerStep + 1]
4855  - bayer[bayerStep + 3]
4856  - bayer[bayerStep3 + 1]
4857  - bayer[bayerStep3 + 3]
4858  - bayer[bayerStep2 + 4]
4859  + ((bayer[2] + bayer[bayerStep4 + 2] + 1) >> 1);
4860  t0 = (t0 + 4) >> 3;
4861  CLIP16<unsigned short>((unsigned short&)t0,rgb[-blue],bits);
4862  t1 = (t1 + 4) >> 3;
4863  CLIP16<unsigned short>((unsigned short&)t1,rgb[blue],bits);
4864 
4865  bayer++;
4866  rgb += 3;
4867  }
4868 
4869  if (blue > 0) {
4870  for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
4871  /* B at B */
4872  rgb[1] = bayer[bayerStep2 + 2];
4873  /* R at B */
4874  t0 = ((bayer[bayerStep + 1] + bayer[bayerStep + 3] +
4875  bayer[bayerStep3 + 1] + bayer[bayerStep3 + 3]) << 1)
4876  -
4877  (((bayer[2] + bayer[bayerStep2] +
4878  bayer[bayerStep2 + 4] + bayer[bayerStep4 +
4879  2]) * 3 + 1) >> 1)
4880  + rgb[1] * 6;
4881  /* G at B */
4882  t1 = ((bayer[bayerStep + 2] + bayer[bayerStep2 + 1] +
4883  bayer[bayerStep2 + 3] + bayer[bayerStep3 + 2]) << 1)
4884  - (bayer[2] + bayer[bayerStep2] +
4885  bayer[bayerStep2 + 4] + bayer[bayerStep4 + 2])
4886  + (rgb[1] << 2);
4887  t0 = (t0 + 4) >> 3;
4888  CLIP16<unsigned short>((unsigned short&)t0, rgb[-1],bits);
4889  t1 = (t1 + 4) >> 3;
4890  CLIP16<unsigned short>((unsigned short&)t1, rgb[0],bits);
4891  /* at green pixel */
4892  rgb[3] = bayer[bayerStep2 + 3];
4893  t0 = rgb[3] * 5
4894  + ((bayer[bayerStep + 3] + bayer[bayerStep3 + 3]) << 2)
4895  - bayer[3]
4896  - bayer[bayerStep + 2]
4897  - bayer[bayerStep + 4]
4898  - bayer[bayerStep3 + 2]
4899  - bayer[bayerStep3 + 4]
4900  - bayer[bayerStep4 + 3]
4901  +
4902  ((bayer[bayerStep2 + 1] + bayer[bayerStep2 + 5] +
4903  1) >> 1);
4904  t1 = rgb[3] * 5 +
4905  ((bayer[bayerStep2 + 2] + bayer[bayerStep2 + 4]) << 2)
4906  - bayer[bayerStep2 + 1]
4907  - bayer[bayerStep + 2]
4908  - bayer[bayerStep + 4]
4909  - bayer[bayerStep3 + 2]
4910  - bayer[bayerStep3 + 4]
4911  - bayer[bayerStep2 + 5]
4912  + ((bayer[3] + bayer[bayerStep4 + 3] + 1) >> 1);
4913  t0 = (t0 + 4) >> 3;
4914  CLIP16<unsigned short>((unsigned short&)t0,rgb[2],bits);
4915 
4916  t1 = (t1 + 4) >> 3;
4917  CLIP16<unsigned short>((unsigned short&)t1,rgb[4],bits);
4918  }
4919  } else {
4920  for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
4921  /* R at R */
4922  rgb[-1] = bayer[bayerStep2 + 2];
4923  /* B at R */
4924  t0 = ((bayer[bayerStep + 1] + bayer[bayerStep + 3] +
4925  bayer[bayerStep3 + 1] + bayer[bayerStep3 + 3]) << 1)
4926  -
4927  (((bayer[2] + bayer[bayerStep2] +
4928  bayer[bayerStep2 + 4] + bayer[bayerStep4 +
4929  2]) * 3 + 1) >> 1)
4930  + rgb[-1] * 6;
4931  /* G at R */
4932  t1 = ((bayer[bayerStep + 2] + bayer[bayerStep2 + 1] +
4933  bayer[bayerStep2 + 3] + bayer[bayerStep * 3 +
4934  2]) << 1)
4935  - (bayer[2] + bayer[bayerStep2] +
4936  bayer[bayerStep2 + 4] + bayer[bayerStep4 + 2])
4937  + (rgb[-1] << 2);
4938  t0 = (t0 + 4) >> 3;
4939  CLIP16<unsigned short>((unsigned short&)t0,rgb[1],bits);
4940  t1 = (t1 + 4) >> 3;
4941  CLIP16<unsigned short>((unsigned short&)t1,rgb[0],bits);
4942 
4943  /* at green pixel */
4944  rgb[3] = bayer[bayerStep2 + 3];
4945  t0 = rgb[3] * 5
4946  + ((bayer[bayerStep + 3] + bayer[bayerStep3 + 3]) << 2)
4947  - bayer[3]
4948  - bayer[bayerStep + 2]
4949  - bayer[bayerStep + 4]
4950  - bayer[bayerStep3 + 2]
4951  - bayer[bayerStep3 + 4]
4952  - bayer[bayerStep4 + 3]
4953  +
4954  ((bayer[bayerStep2 + 1] + bayer[bayerStep2 + 5] +
4955  1) >> 1);
4956  t1 = rgb[3] * 5 +
4957  ((bayer[bayerStep2 + 2] + bayer[bayerStep2 + 4]) << 2)
4958  - bayer[bayerStep2 + 1]
4959  - bayer[bayerStep + 2]
4960  - bayer[bayerStep + 4]
4961  - bayer[bayerStep3 + 2]
4962  - bayer[bayerStep3 + 4]
4963  - bayer[bayerStep2 + 5]
4964  + ((bayer[3] + bayer[bayerStep4 + 3] + 1) >> 1);
4965  t0 = (t0 + 4) >> 3;
4966  CLIP16<unsigned short>((unsigned short&)t0,rgb[4],bits);
4967  t1 = (t1 + 4) >> 3;
4968  CLIP16<unsigned short>((unsigned short&)t1,rgb[2],bits);
4969  }
4970  }
4971 
4972  if (bayer < bayerEnd) {
4973  /* B at B */
4974  rgb[blue] = bayer[bayerStep2 + 2];
4975  /* R at B */
4976  t0 = ((bayer[bayerStep + 1] + bayer[bayerStep + 3] +
4977  bayer[bayerStep3 + 1] + bayer[bayerStep3 + 3]) << 1)
4978  -
4979  (((bayer[2] + bayer[bayerStep2] +
4980  bayer[bayerStep2 + 4] + bayer[bayerStep4 +
4981  2]) * 3 + 1) >> 1)
4982  + rgb[blue] * 6;
4983  /* G at B */
4984  t1 = (((bayer[bayerStep + 2] + bayer[bayerStep2 + 1] +
4985  bayer[bayerStep2 + 3] + bayer[bayerStep3 + 2])) << 1)
4986  - (bayer[2] + bayer[bayerStep2] +
4987  bayer[bayerStep2 + 4] + bayer[bayerStep4 + 2])
4988  + (rgb[blue] << 2);
4989  t0 = (t0 + 4) >> 3;
4990  CLIP16<unsigned short>((unsigned short&)t0,rgb[-blue],bits);
4991  t1 = (t1 + 4) >> 3;
4992  CLIP16<unsigned short>((unsigned short&)t1,rgb[0],bits);
4993 
4994  bayer++;
4995  rgb += 3;
4996  }
4997 
4998 
4999  bayer -= width;
5000  rgb -= width * 3;
5001 
5002  blue = -blue;
5003  start_with_green = !start_with_green;
5004  }
5005 
5006 
5007  return 0;
5008 }
5009 
5010 template<class StorageType>
5011 int ImageConvert::BayerToRGBAHD_(const StorageType* source, StorageType* dest, int sx, int sy, ImageBase::EColorModel tile, int bits){
5012 
5013  return 0;
5014 }
5015 
5016 template <class StorageType>
5017 void ImageConvert::CLIP(StorageType& in, StorageType& out){
5018  in = in < 0 ? 0 : in;
5019  in = in > 255 ? 255 : in;
5020  out=in;
5021 }
5022 
5023 template <class StorageType>
5024 void ImageConvert::CLIP16(StorageType& in, StorageType& out, StorageType bits){
5025  in = in < 0 ? 0 : in;
5026  in = in > ((1<<bits)-1) ? ((1<<bits)-1) : in;
5027  out=in;
5028 }
5029 
5030 //
5031 // solve explicit instantiation of this class
5032 // must be at the end of the file JW
5033 #include "ImageConvertInstantiation.cpp"
5034 
EColorModel
These are the most often used color models.
Definition: ImageBase.hh:127
void Release()
reimplemented from ImageBase
Definition: Image.cpp:1579
static int GreyToRGB_(const Image< StorageType > &source, Image< StorageType > &dest)
static int IP_RGBToGrey_(Image< StorageType > &img)
void SetBitDepth(unsigned bitdepth)
needed by ImageIO
Definition: ImageBase.hh:581
void PrintHeader(std::ostream &os=std::cout) const
Definition: ImageBase.cpp:905
static int BayerToGrey_(const Image< StorageType > &source, Image< StorageType > &dest)
interpolates, better than above
(16bit) unsigned integer image storage type
Definition: ImageBase.hh:114
static int BayerToRGBSlow_(const Image< StorageType > &source, Image< StorageType > &dest)
this is the right way, green interpoaltion is mostly done out of two values no visible difference to ...
unsigned int GetDepth() const
returns the bytes per channel, which is the sizeof(StorageType) Should match GetSizeDepth(GetStorageT...
Definition: ImageBase.hh:328
HSL, similar to HSV but space is a double tipped cone.
Definition: ImageBase.hh:147
gray values, 1 channel
Definition: ImageBase.hh:130
int SetCorners(unsigned UpperLeftX, unsigned UpperLeftY, unsigned LowerRightX, unsigned LowerRightY)
Sets a rectangular region of interest.
Definition: ROI.cpp:287
void GetCorners(unsigned &UpperLeftX, unsigned &UpperLeftY, unsigned &LowerRightX, unsigned &LowerRightY) const
Return the region of interest, by saving the coordinates within the variables defined by the paramete...
Definition: ROI.hh:443
unsigned int Depth_
size of one channel of one pixel in bytes
Definition: ImageBase.hh:1060
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
bool IsInterleaved() const
Definition: ImageBase.hh:491
(8bit) signed char image storage type
Definition: ImageBase.hh:113
unsigned int GetWidthStep() const
returns the number of bytes per line
Definition: ImageBase.hh:400
void SetColorModel(EColorModel Model)
Definition: ImageBase.hh:561
unsigned int GetSizeByte() const
returns the nr.
Definition: ImageBase.hh:352
float image storage type
Definition: ImageBase.hh:118
static int YUV411ToGrey_(const Image< StorageType > &source, Image< StorageType > &dest)
unsigned int WidthStep_
size of a line in bytes for interleaved, NOT nr . of pixels (but size a line in one plane for planar)...
Definition: ImageBase.hh:1072
bool IsPlanar() const
Definition: ImageBase.hh:484
double image storage type
Definition: ImageBase.hh:119
static void ConvertRGBToI1I2I3Worker_(const sourceType *soP, float *siP, int size)
static int YUV420PToRGB_(const Image< StorageType > &source, Image< StorageType > &dest)
unsigned int GetWidth() const
Definition: ImageBase.hh:312
unsigned int GetBitDepth() const
returns the bits per channel Is not necessairily 8*sizeof(StorageType), could be fewer bits...
Definition: ImageBase.hh:344
StorageType PixelValue(const unsigned int x, const unsigned int y, const unsigned short int channel=0) const
Returns value of pixel at specific position, using specific channel as offset.
Definition: Image.hh:91
static int GetChannel(const Image< StorageType > &source, Image< StorageType > &dest, const unsigned int channel)
Create a new image dest by cropping one of the source images channels.
static int ToRGBA(const Image< StorageType > &source, Image< StorageType > &dest)
Create a RGBA converted copy of source image in dest.
(16bit) signed integer image storage type
Definition: ImageBase.hh:115
color values, 3 channels, order: blue,green,red
Definition: ImageBase.hh:132
const void * GetImageData() const
Definition: ImageBase.hh:280
static int BGRToRGB_(const Image< StorageType > &source, Image< StorageType > &dest)
static int BayerToRGB_(const Image< StorageType > &source, Image< StorageType > &dest)
added border calculation, woelk evers, woelk
static int DVToRGB_(const Image< StorageType > &source, Image< StorageType > &dest, unsigned char quality=4)
foreign image formats, ipl, vil, ImageMagick
BayerDemosaicMethod
methods for conversion from bayer to rgb
Definition: ImageConvert.hh:70
static int RGBToI1I2I3(const BIAS::ImageBase &source, BIAS::Image< float > &dest)
Converts RGB image to Othe&#39;s principle component generalization for RGB based segmentation.
static int YUV420PToGrey_(const Image< StorageType > &source, Image< StorageType > &dest)
ROI * GetROI()
Returns a pointer to the roi object.
Definition: ImageBase.hh:615
static int BGRAToGrey_(const Image< StorageType > &source, Image< StorageType > &dest)
not tested - use at own risk - alpha channel will be ignored
void ** GetImageDataArray() const
Get an array of pointers to image data.
Definition: ImageBase.hh:305
int StealImage(ImageBase &source)
steals the image data array from source, after releasing the actual image data and sets source image ...
Definition: ImageBase.cpp:395
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
color values, 3 channels, order: red,green,blue
Definition: ImageBase.hh:131
unsigned int GetHeight() const
Definition: ImageBase.hh:319
static int HSLToGrey_(const Image< StorageType > &source, Image< StorageType > &dest)
just copies the L channel
int SetROI(unsigned int UpperLeftX, unsigned int UpperLeftY, unsigned int LowerRightX, unsigned int LowerRightY)
deprecated, use SetROICorners()
Definition: ImageBase.cpp:1033
void SetPixel(const StorageType &value, const unsigned int &x, const unsigned int &y, const unsigned short int channel=0)
Set the value of a given pixel (x,y) in channel to value.
Definition: Image.hh:171
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
Definition: Image.cpp:421
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
Definition: Image.hh:137
RGBA, 4 channels, order: red,green,blue,alpha.
Definition: ImageBase.hh:141
unsigned int ChannelCount_
number of channels per pixel
Definition: ImageBase.hh:1058
void Release(const bool reset_storage_type=false)
Free the allocated data structures Hands off: Do !!NOT!! change the default of reset_storage_type: Im...
Definition: ImageBase.cpp:350
enum EColorModel GetColorModel() const
Definition: ImageBase.hh:407
(32bit) signed integer image storage type
Definition: ImageBase.hh:117
void Init(unsigned int width, unsigned int height, unsigned int nChannels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
Initialize image size and channels.
Definition: ImageBase.cpp:229
void ReleaseImageDataPointer()
Releases ImageData_ (to be used together with RedirectImageDataPointer)
Definition: ImageBase.hh:90
static int BIAS2ImageMagick(const BIAS::ImageBase &input, Magick::Image &dest)
Returns a new, separate ImageMagick Image for use with ImageMagick created from the source BIAS Image...
static int IP_YUV422ToGrey_(Image< StorageType > &img)
enum EStorageType GetStorageType() const
Definition: ImageBase.hh:414
(8bit) unsigned char image storage type
Definition: ImageBase.hh:112
static int BayerToRGB(const Image< StorageType > &source, Image< StorageType > &dest, BayerDemosaicMethod method=BAYER_DEMOSAIC_METHOD_BILINEAR, bool flip=false)
converts an image with bayer pattern to rgb
HSV, 3 channels, order: hue, sat , value.
Definition: ImageBase.hh:138
int UpdateImageDataArrayFromImageData_()
recomputes pointer array returned by GetImageDataArray
Definition: ImageBase.cpp:302
static int RGBToGrey_(const Image< StorageType > &source, Image< StorageType > &dest)
static int ImageMagick2BIAS(Magick::Image &image, BIAS::ImageBase &result)
Returns a new, separate BIAS Image created from the source ImageMagick Image.
static int YUV422ToRGB_(const Image< StorageType > &source, Image< StorageType > &dest)
void * ImageData_
a pointer to the image data
Definition: ImageBase.hh:1076
static int RGBAToRGB_(const Image< StorageType > &source, Image< StorageType > &dest)
unsigned long int GetPixelCount() const
returns number of pixels in image
Definition: ImageBase.hh:422
GreyA, 2 channels, grey plus Alpha.
Definition: ImageBase.hh:142
This is the base class for images in BIAS.
Definition: ImageBase.hh:102
void RedirectImageDataPointer(void *data)
This method takes data and set the internal image data pointer to this.
Definition: ImageBase.hh:859
static int ToRGB(const Image< StorageType > &source, Image< StorageType > &dest)
Create a RGB converted copy of source image in this.
int FlipHorizontal()
flips the image horizontal (column order is inverted) In place function return 0 in case of success...
Definition: ImageBase.cpp:878
static int BGRAToRGB_(const Image< StorageType > &source, Image< StorageType > &dest)
unsigned int Width_
image width in pixels
Definition: ImageBase.hh:1064
enum EColorModel ColorModel_
the color model of the pixels
Definition: ImageBase.hh:1054
static int YUV422ToGrey_(const Image< StorageType > &source, Image< StorageType > &dest)
static int IP_ToGrey(Image< StorageType > &img)
In place conversion to gray image.
(32bit) unsigned integer image storage type
Definition: ImageBase.hh:116
static int ToGrey(const ImageBase &source, ImageBase &dest)
wrapper for the templated function ToGrey