Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ToHSL.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003, 2004 (see file CONTACTS 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 #include "ImageIO.hh"
27 
28 using namespace BIAS;
29 
30 
31 namespace BIAS
32 {
33 
34 template <class StorageType>
35 BIASImageBase_EXPORT
37  Image<StorageType> &dest)
38 {
39  int res = -1;
40 
41  if (dest.IsEmpty())
42  dest.Init(source.GetWidth(), source.GetHeight(), 3,
43  source.GetStorageType());
44 
45 
46 
47 #ifdef BIAS_DEBUG
48  if ( (dest.GetHeight()!=source.GetHeight()) ||
49  (dest.GetWidth()!=source.GetWidth()) ) {
50  BIASERR("ImageConvert::ToHSL() should be called with images of"\
51  <<" same size");
52  }
53 #endif
54 
55  switch (source.GetColorModel()) {
56  case ImageBase::CM_RGB:
57  res = RGBToHSL_(source,dest);
58  break;
59  case ImageBase::CM_BGR:
60  res = BGRToHSL_(source,dest);
61  break;
62  case ImageBase::CM_BGRA:
63  res = BGRAToHSL_(source,dest);
64  break;
67  res = ImageConvert::ToRGB(source,tmp);
68  res = ToHSL(tmp,dest);
69  break;
70  }
71  default:
72  BIASERR("Image::ToHSL(): color model not implemented for "<<
73  source.GetColorModel());
74  break;
75  }
77  return res;
78 }
79 
80 
81 
82 template <class StorageType>
84  Image<StorageType> &/*dest*/)
85 {
86  BIASERR("ImageConvert::RGBToHSL only for <float> and <unsgined char> not "<<
87  source.GetStorageType());
88  return -1;
89 }
90 
91 
92 // S and L in [0..1]
93 // H in [0..360] where red is 360=0 , blue is 240 and green is 120;
94 template <>
96  Image<float> &dest) {
97  BIASWARN("Unnecessary image copy operation. This may hurt performance.");
98  Image<float> source(source1);
99 
100  register float *R = source.GetImageData();
101  register float *G = NULL , *B = NULL;
102  register float *ImageDataEnd =
103  R + source.GetPixelCount() * source.GetChannelCount();
104  register float *H = dest.GetImageData();
105  register float *S = NULL , *L = NULL;
106  register float Min = 0, Max = 0;
107  float MinVal = 0, MaxVal = 0;
108 
109  // scale image so RGB Values are between 0.0 and 1.0
110  // if necessary
111  for (unsigned short int i = 0; i < dest.GetChannelCount(); i++){
112  source.GetMinMaxPixelValue(Min, Max, i);
113  if (Max > MaxVal)
114  MaxVal = Max;
115  if (Min < MinVal)
116  MinVal = Min;
117  }
118  if ( (MinVal < 0.0) || (MaxVal > 1.0) )
119  source.ScaleShiftBetween(0.0, 1.0);
120 
121  if (source.IsPlanar()){
122 
123  G = R + source.GetPixelCount();
124  B = G + source.GetPixelCount();
125  S = H + dest.GetPixelCount();
126  L = S + dest.GetPixelCount();
127  while (R < ImageDataEnd){
128  // calc Max and Min
129  if ( (*R >= *G) && (*R >= *B) ){
130  Max = *R;
131  if (*G <= *B)
132  Min = *G;
133  else
134  Min = *B;
135  } else if (*G >= *B){
136  Max = *G;
137  if (*B <= *R)
138  Min = *B;
139  else
140  Min = *R;
141  } else {
142  Max = *B;
143  if (*R <= *G)
144  Min = *R;
145  else
146  Min = *G;
147  }
148  *L = (Max + Min) / 2.0f;
149  if (Max == Min){
150  *H = 240;
151  *S = 0;
152  } else {
153  // Saturation
154  if ((*L) < 0.5 ) *S=(Max-Min)/(Max+Min);
155  else *S=(Max-Min)/(2.0f-Max-Min);
156  // H (ue)
157  if (*R == Max)
158  *H = (*G - *B)/(Max - Min);
159  else if (*G == Max)
160  *H = 2.0f + (*B - *R)/(Max - Min);
161  else // (*B == Max)
162  *H = 4.0f + (*R - *G)/(Max - Min);
163  *H *= 60;
164  if (*H < 0)
165  *H += 360;
166  }
167  // increase pointers
168  H++;
169  S++;
170  L++;
171  R++;
172  G++;
173  B++;
174  }
175  dest.SetInterleaved(false);
177 
178  } else { // source is interleaved
179  S = H + 1;
180  L = H + 2;
181  while (R < ImageDataEnd){
182  // calculate Min(R,G,B) and Max(R,G,B)
183  Max = Min = R[0];
184  for (register int i = 1; i < 3; i++){
185  if ( Max < R[i])
186  Max = R[i];
187  if (Min > R[i])
188  Min = R[i];
189  }
190  G = R+1;
191  B = R+2;
192  *L = (Max + Min) / 2.0f;
193  if (Max == Min){
194  *H = 240;
195  *S = 0;
196  } else {
197  // Saturation
198  if ((*L) < 0.5 ) *S=(Max-Min)/(Max+Min);
199  else *S=(Max-Min)/(2.0f-Max-Min);
200  // H (ue)
201  if (*R == Max)
202  *H = (*G - *B)/(Max - Min);
203  else if (*G == Max)
204  *H = 2.0f + (*B - *R)/(Max - Min);
205  else // (*B == Max)
206  *H = 4.0f + (*R - *G)/(Max - Min);
207  *H *= 60;
208  if (*H < 0)
209  *H += 360;
210  }
211 
212  // increase pointers
213  H+=3;
214  S+=3;
215  L+=3;
216  R+=3;
217  }
218  dest.SetInterleaved(true);
220  }
221  return 0;
222 }
223 
224 
225 // H [0,255] 0 = red, 85 = green , 171 = blue
226 // saturation [0,255]
227 // lighting [0,255]
228 // by Daniel Grest, April 2003
229 template <>
231  Image<unsigned char> &dest)
232 {
233 #ifdef BIAS_DEBUG
234  if (source.GetColorModel() != ImageBase::CM_RGB){
235  BIASERR("source not in RGB format");
236  return -1;
237  }
238 #endif
239  register const unsigned char *R = source.GetImageData();
240  register const unsigned char *ImageDataEnd =
241  R + source.GetSizeByte();
242  register unsigned char *H = dest.GetImageData();
243  register const unsigned char *G = NULL, *B = NULL;
244  register unsigned char *S = NULL, *L = NULL;
245  register int Min = 0, Max = 0;
246  register int delta,TmpH;
247 
248  if (source.IsPlanar()){
249  G = R + source.GetPixelCount();
250  B = G + source.GetPixelCount();
251  S = H + dest.GetPixelCount();
252  L = S + dest.GetPixelCount();
253  while (R < ImageDataEnd){
254  // calc Max and Min
255  Max = Min = *R;
256  if (Max < *G) Max=*G;
257  if (Max < *B) Max=*B;
258  if (Min > *G) Min=*G;
259  if (Min > *B) Min=*B;
260 
261  *L = (unsigned char)((Max + Min) / 2);
262 
263  delta = Max - Min;
264  if (delta==0){
265  *H = 171;
266  *S = 0;
267  } else {
268  // Saturation
269  if ((*L) < 127)
270  *S= (unsigned char)(int(255*delta)/ int(Max+Min));
271  else *S= (unsigned char)(int(255*delta)/int(510-Max-Min));
272 
273  // H (ue)
274  if (*R == Max)
275  TmpH = (255 * (*G - *B)) / delta;
276  else if (*G == Max)
277  TmpH = 510 + (255 * (*B - *R)) / delta;
278  else // (*B == Max)
279  TmpH = 1020 + (255 * (*R - *G)) / delta;
280  TmpH /= 6;
281  if (TmpH < 0)
282  *H = (unsigned char)(TmpH + 255);
283  else
284  *H = (unsigned char)TmpH;
285  }
286 
287  // increase pointers
288  H++; S++; L++; R++; G++; B++;
289  }
290  dest.SetInterleaved(false);
292  } else {// source is interleaved
293  G = R + 1;
294  B = G + 1;
295  S = H + 1;
296  L = S + 1;
297  while (R < ImageDataEnd){
298  // calculate Min(R,G,B) and Max(R,G,B)
299  Max = Min = *R;
300  if (Max < *G) Max=*G;
301  if (Max < *B) Max=*B;
302  if (Min > *G) Min=*G;
303  if (Min > *B) Min=*B;
304 
305  *L = (unsigned char)((Max + Min) / 2);
306 
307  delta = Max - Min;
308  if (delta==0){
309  *H = 171;
310  *S = 0;
311  } else {
312  // Saturation
313 
314  if ((*L) < 127)
315  *S= (unsigned char)rint(float(255*delta)/ float(Max+Min));
316  else *S= (unsigned char)rint(float(255*delta)/float(510-Max-Min));
317 
318  // H (ue)
319  if (*R == Max)
320  TmpH = (255 * (*G - *B)) / delta;
321  else if (*G == Max)
322  TmpH = 510 + (255 * (*B - *R)) / delta;
323  else // (*B == Max)
324  TmpH = 1020 + (255 * (*R - *G)) / delta;
325  TmpH /= 6;
326  if (TmpH < 0)
327  *H = (unsigned char)(TmpH + 255);
328  else
329  *H = (unsigned char)TmpH;
330  }
331 
332  // increase pointers
333  H+=3;
334  S+=3;
335  L+=3;
336  R+=3;G+=3;B+=3;
337  }
338  dest.SetInterleaved(true);
340  }
341  return 0;
342 }
343 
344 
345 ///////////////////////////// BGR //////////////////////////////
346 
347 template <class StorageType>
349  Image<StorageType> &/*dest*/)
350 {
351  BIASERR("ImageConvert::BGRToHSL only for <unsgined char> not "<<
352  source.GetStorageType());
353  return -1;
354 }
355 
356 
357 // H [0,255] 0 = red, 85 = green , 171 = blue
358 // saturation [0,255]
359 // lighting [0,255]
360 // by Daniel Grest, April 2003
361 template <>
363  Image<unsigned char> &dest)
364 {
365 #ifdef BIAS_DEBUG
366  if (source.GetColorModel() != ImageBase::CM_BGR){
367  BIASERR("source not in BGR format");
368  return -1;
369  }
370 #endif
371  register const unsigned char *B = source.GetImageData();
372  register const unsigned char *ImageDataEnd =
373  B + source.GetSizeByte();
374  register unsigned char *H = dest.GetImageData();
375  register const unsigned char *G = NULL, *R = NULL;
376  register unsigned char *S = NULL, *L = NULL;
377  register unsigned char Min = 0, Max = 0;
378  register int delta,TmpH;
379 
380  if (source.IsPlanar()){
381  G = B + source.GetPixelCount();
382  R = G + source.GetPixelCount();
383  S = H + dest.GetPixelCount();
384  L = S + dest.GetPixelCount();
385  while (B < ImageDataEnd){
386  // calc Max and Min
387  Max = Min = *R;
388  if (Max < *G) Max=*G;
389  if (Max < *B) Max=*B;
390  if (Min > *G) Min=*G;
391  if (Min > *B) Min=*B;
392 
393  *L = (Max + Min) / 2;
394 
395  delta = Max - Min;
396  if (delta==0){
397  *H = 171;
398  *S = 0;
399  } else {
400  // Saturation
401  if ((*L) > 127)
402  *S= (unsigned char)((255*delta)/ (Max+Min));
403  else *S= (unsigned char)((255*delta)/(510-delta));
404  // H (ue)
405  if (*R == Max)
406  TmpH = (255 * (*G - *B)) / delta;
407  else if (*G == Max)
408  TmpH = 510 + (255 * (*B - *R)) / delta;
409  else // (*B == Max)
410  TmpH = 1020 + (255 * (*R - *G)) / delta;
411  TmpH /= 6;
412  if (TmpH < 0)
413  *H = (unsigned char)(TmpH + 255);
414  else
415  *H = (unsigned char)TmpH;
416  }
417 
418  // increase pointers
419  H++; S++; L++; R++; G++; B++;
420  }
421  dest.SetInterleaved(false);
423  } else {// source is interleaved
424  G = B + 1;
425  R = G + 1;
426  S = H + 1;
427  L = S + 1;
428  while (B < ImageDataEnd){
429  // calulate Min(R,G,B) and Max(R,G,B)
430  Max = Min = *R;
431  if (Max < *G) Max=*G;
432  if (Max < *B) Max=*B;
433  if (Min > *G) Min=*G;
434  if (Min > *B) Min=*B;
435 
436  *L = (Max + Min) / 2;
437 
438  delta = Max - Min;
439  if (delta==0){
440  *H = 171;
441  *S = 0;
442  } else {
443  // Saturation
444  if ((*L) > 127)
445  *S= (unsigned char)((255*delta)/ (Max+Min));
446  else *S= (unsigned char)((255*delta)/(510-delta));
447  // H (ue)
448  if (*R == Max)
449  TmpH = (255 * (*G - *B)) / delta;
450  else if (*G == Max)
451  TmpH = 510 + (255 * (*B - *R)) / delta;
452  else // (*B == Max)
453  TmpH = 1020 + (255 * (*R - *G)) / delta;
454  TmpH /= 6;
455  if (TmpH < 0)
456  *H = (unsigned char)(TmpH + 255);
457  else
458  *H = (unsigned char)TmpH;
459  }
460 
461  // increase pointers
462  H+=3;
463  S+=3;
464  L+=3;
465  R+=3;G+=3;B+=3;
466  }
467  dest.SetInterleaved(true);
469  }
470  return 0;
471 }
472 
473 
474 ///////////////////////////// BGRA //////////////////////////////
475 
476 template <class StorageType>
478  Image<StorageType> &/*dest*/)
479 {
480  BIASERR("ImageConvert::BGRAToHSL only for <unsgined char> not "<<
481  source.GetStorageType());
482  return -1;
483 }
484 
485 
486 // H [0,255] 0 = red, 85 = green , 171 = blue
487 // saturation [0,255]
488 // lighting [0,255]
489 // by Daniel Grest, Feb 2005
490 template <>
492  Image<unsigned char> &dest)
493 {
494 #ifdef BIAS_DEBUG
495  if (source.GetColorModel() != ImageBase::CM_BGRA){
496  BIASERR("source not in BGRA format");
497  return -1;
498  }
499 #endif
500  register const unsigned char *B = source.GetImageData();
501  register const unsigned char *ImageDataEnd =
502  B + source.GetSizeByte();
503  register unsigned char *H = dest.GetImageData();
504  register const unsigned char *G = NULL, *R = NULL;
505  register unsigned char *S = NULL, *L = NULL;
506  register unsigned char Min = 0, Max = 0;
507  register int delta,TmpH;
508 
509  if (source.IsPlanar()){
510  BIASERR("BGRAToHSL_() not for planar images");
511  return -2;
512  } else {// source is interleaved
513  G = B + 1;
514  R = G + 1;
515  S = H + 1;
516  L = S + 1;
517  while (B < ImageDataEnd){
518  // calulate Min(R,G,B) and Max(R,G,B)
519  Max = Min = *R;
520  if (Max < *G) Max=*G;
521  if (Max < *B) Max=*B;
522  if (Min > *G) Min=*G;
523  if (Min > *B) Min=*B;
524 
525  *L = (Max + Min) / 2;
526 
527  delta = Max - Min;
528  if (delta==0){
529  *H = 171;
530  *S = 0;
531  } else {
532  // Saturation
533  if ((*L) > 127)
534  *S= (unsigned char)((255*delta)/ (Max+Min));
535  else *S= (unsigned char)((255*delta)/(510-delta));
536  // H (ue)
537  if (*R == Max)
538  TmpH = (255 * (*G - *B)) / delta;
539  else if (*G == Max)
540  TmpH = 510 + (255 * (*B - *R)) / delta;
541  else // (*B == Max)
542  TmpH = 1020 + (255 * (*R - *G)) / delta;
543  TmpH /= 6;
544  if (TmpH < 0)
545  *H = (unsigned char)(TmpH + 255);
546  else
547  *H = (unsigned char)TmpH;
548  }
549 
550  // increase pointers
551  H+=3;
552  S+=3;
553  L+=3;
554  R+=4;G+=4;B+=4;
555  }
556  dest.SetInterleaved(true);
558  }
559  return 0;
560 }
561 
562 
563 
564 
565 ///////////////////////////////////////////////////////////////////////////
566 /////////////////////////// hsL ///////////////////////////////////////////
567 ///////////////////////////////////////////////////////////////////////////
568 
569 template <class StorageType>
570 BIASImageBase_EXPORT
572  Image<StorageType> &dest)
573 {
574  int res = -1;
575 
576  if (dest.IsEmpty())
577  dest.Init(source.GetWidth(), source.GetHeight(), source.GetChannelCount(),
578  source.GetStorageType());
579 
580  BIASASSERT(source.GetBitDepth() == 8);
581 
582 #ifdef BIAS_DEBUG
583  if (!dest.SamePixelAndChannelCount(source)){
584  BIASERR("ImageConvert::TohsL() should be called with images of"\
585  <<" same size");
586  }
587 #endif
588 
589  switch (source.GetColorModel()) {
590  case ImageBase::CM_RGB:
591  res = RGBTohsL_(source,dest);
592  break;
593  default:
594  BIASERR("Image::TohsL(): color model not implemented for "<<
595  source.GetColorModel());
596  break;
597  }
599  return res;
600 }
601 
602 template <class StorageType>
604  Image<StorageType> &/*dest*/)
605 {
606  BIASERR("ImageConvert::RGBTohsL only for <int> and <unsigned char> and <float> (bit depth 8 for each type)"<<
607  " so far, not "<<
608  source.GetStorageType());
609  return -1;
610 }
611 
612 // (h,s) is the euclidean vector of the(H,S) polar coordinates
613 // lighting [0,255]
614 // by Daniel Grest, June 2003
615 template <>
616 BIASImageBase_EXPORT
618  Image<int> &dest)
619 {
620 #ifdef BIAS_DEBUG
621  if (source.GetColorModel() != ImageBase::CM_RGB){
622  BIASERR("source not in RGB format");
623  return -1;
624  }
625 #endif
626  register const int *R = source.GetImageData();
627  register const int *ImageDataEnd =
628  R + source.GetPixelCount();
629  register int *h = dest.GetImageData();
630  register const int *G = NULL, *B = NULL;
631  register int *s = NULL, *L = NULL;
632  register int Min = 0, Max = 0;
633  register int delta,hTemp,sTemp;
634 
635  register float d=0,sat;
636  if (source.IsPlanar()){
637  BIASERR("not yet implemented");
638  } else {// source is interleaved
639  G = R + 1;
640  B = G + 1;
641  s = h + 1;
642  L = s + 1;
643  while (R < ImageDataEnd){
644  // calulate Min(R,G,B) and Max(R,G,B)
645  Max = Min = *R;
646  if (Max < *G) Max=*G;
647  if (Max < *B) Max=*B;
648  if (Min > *G) Min=*G;
649  if (Min > *B) Min=*B;
650 
651  *L = (Max + Min) / 2;
652 
653  // project RGB
654  hTemp= *G - *B;
655  sTemp= 2*(*R) - *G - *B;
656  d=float(sqrt(double(hTemp*hTemp + sTemp*sTemp)));
657  // if (*L==21) cout<<"d:"<<d<<endl;
658  delta = Max - Min;
659  if ( (delta==0) || (d<1E-07) ) {
660  *h = 0;
661  *s = 0;
662  } else {
663  // Saturation
664  if ((*L) > 127)
665  sat= (float)((255*delta)/ (Max+Min));
666  else sat= (float)((255*delta)/(510-delta));
667  // if (*L==21) cout<<"sat:"<<sat<<endl;
668  *h= (int)((float)hTemp * sat / d + 0.5);
669  *s= (int)((float)sTemp * sat / d + 0.5);
670 
671  }
672 
673  // increase pointers
674  h+=3;
675  s+=3;
676  L+=3;
677  R+=3;G+=3;B+=3;
678  }
679  dest.SetInterleaved(true);
681  }
682  return 0;
683 
684 
685 }
686 
687 
688 
689 // (h,s) is the euclidean vector of the(H,S) polar coordinates
690 // lighting [0,255]
691 // by Daniel Grest, June 2003
692 template <>
693 BIASImageBase_EXPORT
695  Image<float> &dest)
696 {
697 #ifdef BIAS_DEBUG
698  if (source.GetColorModel() != ImageBase::CM_RGB){
699  BIASERR("source not in RGB format");
700  return -1;
701  }
702 #endif
703  register const float *R = source.GetImageData();
704  register const float *ImageDataEnd =
705  R + source.GetPixelCount();
706  register float *h = dest.GetImageData();
707  register const float *G = NULL, *B = NULL;
708  register float *s = NULL, *L = NULL;
709  register float Min = 0, Max = 0;
710  register float delta,hTemp,sTemp;
711 
712  register float d=0,sat;
713  if (source.IsPlanar()){
714  BIASERR("not yet implemented");
715  } else {// source is interleaved
716  G = R + 1;
717  B = G + 1;
718  s = h + 1;
719  L = s + 1;
720  while (R < ImageDataEnd){
721  // calulate Min(R,G,B) and Max(R,G,B)
722  Max = Min = *R;
723  if (Max < *G) Max=*G;
724  if (Max < *B) Max=*B;
725  if (Min > *G) Min=*G;
726  if (Min > *B) Min=*B;
727 
728  *L = (Max + Min) / 2;
729 
730  // project RGB
731  hTemp= *G - *B;
732  sTemp= 2*(*R) - *G - *B;
733  d=float(sqrt(double(hTemp*hTemp + sTemp*sTemp)));
734  // if (*L==21) cout<<"d:"<<d<<endl;
735  delta = Max - Min;
736  if ( (delta==0) || (d<1E-07) ) {
737  *h = 0;
738  *s = 0;
739  } else {
740  // Saturation
741  if ((*L) > 127)
742  sat= (float)((255*delta)/ (Max+Min));
743  else sat= (float)((255*delta)/(510-delta));
744  // if (*L==21) cout<<"sat:"<<sat<<endl;
745  *h= (float)hTemp * sat / d + 0.5f;
746  *s= (float)sTemp * sat / d + 0.5f;
747  }
748 
749  // increase pointers
750  h+=3;
751  s+=3;
752  L+=3;
753  R+=3;G+=3;B+=3;
754  }
755  dest.SetInterleaved(true);
757  }
758  return 0;
759 
760 
761 }
762 
763 
764 
765 // (h,s) is the euclidean vector of the(H,S) polar coordinates
766 // h,s in [-127..127] but stored unsigned char (0..128) !
767 // lighting [0,255]
768 // by Daniel Grest, June 2003
769 template <>
770 BIASImageBase_EXPORT
772  Image<unsigned char> &dest)
773 {
774 #ifdef BIAS_DEBUG
775  if (source.GetColorModel() != ImageBase::CM_RGB){
776  BIASERR("source not in RGB format");
777  return -1;
778  }
779 #endif
780  register const unsigned char *R = source.GetImageData();
781  register const unsigned char *ImageDataEnd =
782  R + source.GetSizeByte();
783  register unsigned char *h = dest.GetImageData();
784  register const unsigned char *G = NULL, *B = NULL;
785  register unsigned char *s = NULL;
786  register unsigned char *L = NULL;
787  register unsigned char Min = 0, Max = 0;
788  register unsigned char delta;
789  register float hTemp,sTemp;
790 
791  register float d=0,sat;
792  if (source.IsPlanar()){
793  BIASERR("not yet implemented");
794  } else {// source is interleaved
795  G = R + 1;
796  B = G + 1;
797  s = h + 1;
798  L = s + 1;
799  while (R < ImageDataEnd){
800  // calulate Min(R,G,B) and Max(R,G,B)
801  Max = Min = *R;
802  if (Max < *G) Max=*G;
803  if (Max < *B) Max=*B;
804  if (Min > *G) Min=*G;
805  if (Min > *B) Min=*B;
806 
807  *L = (Max + Min) / 2;
808 
809  // project RGB
810  hTemp= float((int)*G - (int)*B);
811  sTemp= float(2*(int)(*R) - (int)*G - (int)*B);
812  d=float(sqrt(double(hTemp*hTemp + sTemp*sTemp)));
813  // if (*L==21) cout<<"d:"<<d<<endl;
814  delta = Max - Min;
815  if ( (delta==0) || (d<1E-07) ) {
816  *h = 127;
817  *s = 127;
818  } else {
819  // Saturation
820  if ((*L) > 127)
821  sat= (float)((127*delta)/ (Max+Min));
822  else sat= (float)((127*delta)/(510-delta));
823  // if (*L==21) cout<<"sat:"<<sat<<endl;
824  *h= (unsigned char)(hTemp * sat / d + 127.5);
825  *s= (unsigned char)(sTemp * sat / d + 127.5);
826 
827  }
828 
829  // increase pointers
830  h+=3;
831  s+=3;
832  L+=3;
833  R+=3;G+=3;B+=3;
834  }
835  dest.SetInterleaved(true);
837  }
838  return 0;
839 }
840 
841 // works for interleaved float images, but not for unsigned char, since it
842 // assumes values for hue to be in [0,360], and for S and L in [0,1]
843 template <class StorageType>
845  Image<StorageType>& dest)
846 {
847 #ifdef BIAS_DEBUG
848  if (source.GetColorModel() != ImageBase::CM_HSL){
849  BIASERR("source not in HSL format");
850  return -1;
851  }
852  if(source.GetStorageType() != ImageBase::ST_float){
853  BIASERR("not implemented properly, fix first, only working for float right now")
854  return -1;
855  }
856 #endif
857  unsigned width = source.GetWidth();
858  unsigned height = source.GetHeight();
859  Image<float> tmpIm(width,height,3);
860  Image<float> tmpS(width,height,3);
861 
863  register float **idaS = tmpS.GetImageDataArray();
864  register StorageType **idaD = dest.GetImageDataArray();
865  register float **idaTmp = tmpIm.GetImageDataArray();
866 
867 
868  if(source.IsPlanar()){
869  BIASERR("Only for interleaved images!");
870  return -1;
871  }
872  else{
873  //tmpS.ScaleShiftBetween(0,1.0);
874  // http://130.113.54.154/~monger/hsl-rgb.html
875 //#ifdef BIAS_HAVE_OPENMP
876 //#pragma omp parallel for
877 //#endif
878  for(int y = 0; y<(int)height; y++){
879  for(int x = 0; x<(int)width; x++){
880  //in range 0,1
881  float H = float(idaS[y][x*3])/360.0f;
882  float S = float(idaS[y][x*3+1]);
883  float L = float(idaS[y][x*3+2]);
884 
885  //If S=0, define R, G, and B all to L
886  if(S==0){
887  idaTmp[y][x*3] = idaTmp[y][x*3+1] = idaTmp[y][x*3+2] = L;
888  } else {
889  float tmp1=0.0,tmp2=0.0,tmp3R=0.0, tmp3G=0.0, tmp3B=0.0;
890  if(L<0.5f) tmp2 = L*(1.0f+S);
891  else if (L >=0.5f) tmp2 = (L+S)-(L*S);
892 
893  tmp1 = 2.0f*L-tmp2;
894 
895  tmp3R = H+(1.0f/3.0f); if(tmp3R<0) tmp3R+=1.0f; if(tmp3R>1) tmp3R-=1.0f;
896  tmp3G = H; if(tmp3G<0) tmp3G+=1.0f; if(tmp3G>1) tmp3G-=1.0f;
897  tmp3B = H-(1.0f/3.0f); if(tmp3B<0) tmp3B+=1.0f; if(tmp3B>1) tmp3B-=1.0f;
898  //R
899  if((tmp3R*6.0f) < 1) idaTmp[y][x*3] = tmp1+(tmp2-tmp1)*6.0f*tmp3R;
900  else if((tmp3R*2.0f) < 1) idaTmp[y][x*3]=tmp2;
901  else if((tmp3R*3.0f) < 2) idaTmp[y][x*3]=tmp1+(tmp2-tmp1)*((2.0f/3.0f)-tmp3R)*6.0f;
902  else idaTmp[y][x*3]=tmp1;
903  //G
904  if((tmp3G*6.0f) < 1) idaTmp[y][x*3+1] = tmp1+(tmp2-tmp1)*6.0f*tmp3G;
905  else if((tmp3G*2.0f) < 1) idaTmp[y][x*3+1]=tmp2;
906  else if((tmp3G*3.0f) < 2) idaTmp[y][x*3+1]=tmp1+(tmp2-tmp1)*((2.0f/3.0f)-tmp3G)*6.0f;
907  else idaTmp[y][x*3+1]=tmp1;
908  //B
909  if((tmp3B*6.0f) < 1) idaTmp[y][x*3+2] = tmp1+(tmp2-tmp1)*6.0f*tmp3B;
910  else if((tmp3B*2.0f) < 1) idaTmp[y][x*3+2]=tmp2;
911  else if((tmp3B*3.0f) < 2) idaTmp[y][x*3+2]=tmp1+(tmp2-tmp1)*((2.0f/3.0f)-tmp3B)*6.0f;
912  else idaTmp[y][x*3+2]=tmp1;
913  }//else
914 
915  //scale back to 0 255
916  //cout << "r " << idaTmp[y][x*3] << " g " << idaTmp[y][x*3+1] << " b " << idaTmp[y][x*3+2] << endl;
917  idaD[y][x*3] = StorageType(idaTmp[y][x*3]*(255.0));
918  idaD[y][x*3+1] = StorageType(idaTmp[y][x*3+1]*(255.0));
919  idaD[y][x*3+2] = StorageType(idaTmp[y][x*3+2]*(255.0));
920  }//x
921  }//y
922  dest.SetInterleaved(true);
924  return 0;
925  }
926 }
927 
928 } // namespace BIAS
hsl, similar to HSL but euclidean (h,s) for CNCC
Definition: ImageBase.hh:148
static int BGRAToHSL_(const Image< StorageType > &source, Image< StorageType > &dest)
Definition: ToHSL.cpp:477
HSL, similar to HSV but space is a double tipped cone.
Definition: ImageBase.hh:147
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
int ScaleShiftBetween(double Min, double Max)
scales and shifts image so afterwards every pixel has a value between Min and Max ...
Definition: Image.cpp:1118
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
bool IsPlanar() const
Definition: ImageBase.hh:484
static BIASImageBase_EXPORT int ToHSL(const Image< StorageType > &source, Image< StorageType > &dest)
Create a HSL converted copy of source image in this Release() and Init() are called if necessary...
Definition: ToHSL.cpp:36
static int HSLToRGB_(const BIAS::Image< StorageType > &source, BIAS::Image< StorageType > &dest)
Definition: ToHSL.cpp:844
void GetMinMaxPixelValue(StorageType &min, StorageType &max, unsigned short int channel=0, unsigned int *mincoo=NULL, unsigned int *maxcoo=NULL) const
returns the minimal and maximal pixel value in channel only Finds minimum and maximum pixel value in ...
Definition: Image.cpp:802
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
static BIASImageBase_EXPORT int TohsL(const Image< StorageType > &source, Image< StorageType > &dest)
Create a hsL converted copy of source image in this Release() and Init() are called if necessary...
Definition: ToHSL.cpp:571
void SetInterleaved(bool interleaved)
Definition: ImageBase.hh:568
color values, 3 channels, order: blue,green,red
Definition: ImageBase.hh:132
static int ConvertST(const BIAS::ImageBase &source, BIAS::ImageBase &dest, ImageBase::EStorageType targetST)
Function to convert the storage type of images e.g.
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
UYVY422, 2 channels, full luminance Y, subsampled half U,V inverse order.
Definition: ImageBase.hh:134
static int RGBToHSL_(const Image< StorageType > &source, Image< StorageType > &dest)
Definition: ToHSL.cpp:83
The image template class for specific storage types.
Definition: Image.hh:78
static int BGRToHSL_(const Image< StorageType > &source, Image< StorageType > &dest)
Definition: ToHSL.cpp:348
bool SamePixelAndChannelCount(const ImageBase &Image) const
checks if data area has same &quot;size&quot; as Image of other type
Definition: ImageBase.hh:73
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
enum EColorModel GetColorModel() const
Definition: ImageBase.hh:407
enum EStorageType GetStorageType() const
Definition: ImageBase.hh:414
static int RGBTohsL_(const Image< StorageType > &source, Image< StorageType > &dest)
Definition: ToHSL.cpp:603
unsigned long int GetPixelCount() const
returns number of pixels in image
Definition: ImageBase.hh:422
static int ToRGB(const Image< StorageType > &source, Image< StorageType > &dest)
Create a RGB converted copy of source image in this.
BGRA color values, 4 channels, order: blue,green,red,alpha.
Definition: ImageBase.hh:150
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153