gimpcolorspace.c 13.8 KB
Newer Older
1
2
/* LIBGIMP - The GIMP Library 
 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball                
Marc Lehmann's avatar
Marc Lehmann committed
3
 *
4
5
6
7
8
9
10
11
12
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
 * Library General Public License for more details.
Marc Lehmann's avatar
Marc Lehmann committed
13
 *
14
15
16
17
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Marc Lehmann's avatar
Marc Lehmann committed
18
19
 */

20
21
#include "config.h"

Marc Lehmann's avatar
Marc Lehmann committed
22
23
#include <glib.h>

24
25
#include "libgimpmath/gimpmath.h"

26
27
#include "gimpcolortypes.h"

28
#include "gimpcolorspace.h"
29
30
31
#include "gimprgb.h"
#include "gimphsv.h"

32

Marc Lehmann's avatar
Marc Lehmann committed
33

34
35
36
#define GIMP_HSV_UNDEFINED -1.0
#define GIMP_HSL_UNDEFINED -1.0

Marc Lehmann's avatar
Marc Lehmann committed
37
38
39
40
/*********************************
 *   color conversion routines   *
 *********************************/

41
42
43
44

/*  GimpRGB functions  */

void
45
46
gimp_rgb_to_hsv (const GimpRGB *rgb,
		 GimpHSV       *hsv)
47
48
49
50
{
  gdouble max, min, delta;

  g_return_if_fail (rgb != NULL);
51
  g_return_if_fail (hsv != NULL);
52
53
54
55

  max = gimp_rgb_max (rgb);
  min = gimp_rgb_min (rgb);

56
  hsv->v = max;
Sven Neumann's avatar
Sven Neumann committed
57
  delta = max - min;
58

Sven Neumann's avatar
Sven Neumann committed
59
  if (delta > 0.0001)
60
    {
61
62
      hsv->s = delta / max;

63
64
      if (rgb->r == max)
        {
65
          hsv->h = (rgb->g - rgb->b) / delta;
66
67
68
        }
      else if (rgb->g == max)
        {
69
          hsv->h = 2.0 + (rgb->b - rgb->r) / delta;
70
71
72
        }
      else if (rgb->b == max)
        {
73
          hsv->h = 4.0 + (rgb->r - rgb->g) / delta;
74
75
        }

76
      hsv->h /= 6.0;
77

78
79
80
81
82
83
84
85
      if (hsv->h < 0.0)
        hsv->h += 1.0;
      else if (hsv->h > 1.0)
	hsv->h -= 1.0;
    }
  else
    {
      hsv->s = 0.0;
86
      hsv->h = 0.0;
87
    }
88
89

  hsv->a = rgb->a;
90
91
92
}

void
93
94
gimp_hsv_to_rgb (const GimpHSV *hsv,
		 GimpRGB       *rgb)
95
96
97
98
{
  gint    i;
  gdouble f, w, q, t;

99
100
  gdouble hue;

101
  g_return_if_fail (rgb != NULL);
102
  g_return_if_fail (hsv != NULL);
103

104
  if (hsv->s == 0.0)
105
    {
106
107
108
      rgb->r = hsv->v;
      rgb->g = hsv->v;
      rgb->b = hsv->v;
109
110
111
    }
  else
    {
112
      hue = hsv->h;
113

114
115
      if (hue == 1.0)
        hue = 0.0;
116

117
118
119
120
      hue *= 6.0;

      i = (gint) hue;
      f = hue - i;
121
122
123
      w = hsv->v * (1.0 - hsv->s);
      q = hsv->v * (1.0 - (hsv->s * f));
      t = hsv->v * (1.0 - (hsv->s * (1.0 - f)));
124
125
126
127

      switch (i)
        {
        case 0:
128
          rgb->r = hsv->v;
129
130
131
132
133
          rgb->g = t;
          rgb->b = w;
          break;
        case 1:
          rgb->r = q;
134
          rgb->g = hsv->v;
135
136
137
138
          rgb->b = w;
          break;
        case 2:
          rgb->r = w;
139
          rgb->g = hsv->v;
140
141
142
143
144
          rgb->b = t;
          break;
        case 3:
          rgb->r = w;
          rgb->g = q;
145
          rgb->b = hsv->v;
146
147
148
149
          break;
        case 4:
          rgb->r = t;
          rgb->g = w;
150
          rgb->b = hsv->v;
151
152
          break;
        case 5:
153
          rgb->r = hsv->v;
154
155
156
157
158
          rgb->g = w;
          rgb->b = q;
          break;
        }
    }
159
160

  rgb->a = hsv->a;
161
162
163
}

void
164
gimp_rgb_to_hsl (const GimpRGB *rgb,
Michael Natterer's avatar
Michael Natterer committed
165
                 GimpHSL       *hsl)
166
167
168
169
{
  gdouble max, min, delta;

  g_return_if_fail (rgb != NULL);
Michael Natterer's avatar
Michael Natterer committed
170
  g_return_if_fail (hsl != NULL);
171
172
173
174

  max = gimp_rgb_max (rgb);
  min = gimp_rgb_min (rgb);

Michael Natterer's avatar
Michael Natterer committed
175
  hsl->l = (max + min) / 2.0;
176
177
178

  if (max == min)
    {
Michael Natterer's avatar
Michael Natterer committed
179
180
      hsl->s = 0.0;
      hsl->h = GIMP_HSL_UNDEFINED;
181
182
183
    }
  else
    {
Michael Natterer's avatar
Michael Natterer committed
184
185
      if (hsl->l <= 0.5)
        hsl->s = (max - min) / (max + min);
186
      else
Michael Natterer's avatar
Michael Natterer committed
187
        hsl->s = (max - min) / (2.0 - max - min);
188
189
190

      delta = max - min;

191
192
193
      if (delta == 0.0)
	delta = 1.0;

194
195
      if (rgb->r == max)
        {
Michael Natterer's avatar
Michael Natterer committed
196
          hsl->h = (rgb->g - rgb->b) / delta;
197
198
199
        }
      else if (rgb->g == max)
        {
Michael Natterer's avatar
Michael Natterer committed
200
          hsl->h = 2.0 + (rgb->b - rgb->r) / delta;
201
202
203
        }
      else if (rgb->b == max)
        {
Michael Natterer's avatar
Michael Natterer committed
204
          hsl->h = 4.0 + (rgb->r - rgb->g) / delta;
205
206
        }

Michael Natterer's avatar
Michael Natterer committed
207
      hsl->h /= 6.0;
208

Michael Natterer's avatar
Michael Natterer committed
209
210
      if (hsl->h < 0.0)
        hsl->h += 1.0;
211
    }
Michael Natterer's avatar
Michael Natterer committed
212
213

  hsl->a = rgb->a;
214
215
216
}

static gdouble
217
218
219
gimp_hsl_value (gdouble n1,
                gdouble n2,
                gdouble hue)
220
221
222
{
  gdouble val;

Michael Natterer's avatar
Michael Natterer committed
223
224
  if (hue > 6.0)
    hue -= 6.0;
225
  else if (hue < 0.0)
Michael Natterer's avatar
Michael Natterer committed
226
    hue += 6.0;
227

Michael Natterer's avatar
Michael Natterer committed
228
229
230
  if (hue < 1.0)
    val = n1 + (n2 - n1) * hue;
  else if (hue < 3.0)
231
    val = n2;
Michael Natterer's avatar
Michael Natterer committed
232
233
  else if (hue < 4.0)
    val = n1 + (n2 - n1) * (4.0 - hue);
234
235
236
237
238
239
240
  else
    val = n1;

  return val;
}

void
Michael Natterer's avatar
Michael Natterer committed
241
242
gimp_hsl_to_rgb (const GimpHSL *hsl,
		 GimpRGB       *rgb)
243
{
Michael Natterer's avatar
Michael Natterer committed
244
  g_return_if_fail (hsl != NULL);
245
246
  g_return_if_fail (rgb != NULL);

Michael Natterer's avatar
Michael Natterer committed
247
  if (hsl->s == 0)
248
    {
249
      /*  achromatic case  */
Michael Natterer's avatar
Michael Natterer committed
250
251
252
      rgb->r = hsl->l;
      rgb->g = hsl->l;
      rgb->b = hsl->l;
253
254
255
    }
  else
    {
256
257
      gdouble m1, m2;

Michael Natterer's avatar
Michael Natterer committed
258
259
      if (hsl->l <= 0.5)
        m2 = hsl->l * (1.0 + hsl->s);
260
      else
Michael Natterer's avatar
Michael Natterer committed
261
        m2 = hsl->l + hsl->s - hsl->l * hsl->s;
262

Michael Natterer's avatar
Michael Natterer committed
263
      m1 = 2.0 * hsl->l - m2;
264

Michael Natterer's avatar
Michael Natterer committed
265
266
267
      rgb->r = gimp_hsl_value (m1, m2, hsl->h * 6.0 + 2.0);
      rgb->g = gimp_hsl_value (m1, m2, hsl->h * 6.0);
      rgb->b = gimp_hsl_value (m1, m2, hsl->h * 6.0 - 2.0);
268
    }
Michael Natterer's avatar
Michael Natterer committed
269
270

  rgb->a = hsl->a;
271
272
273
274
275
276
277
278
279
280
281
}

#define GIMP_RETURN_RGB(x, y, z) { rgb->r = x; rgb->g = y; rgb->b = z; return; }

/*****************************************************************************
 * Theoretically, hue 0 (pure red) is identical to hue 6 in these transforms.
 * Pure red always maps to 6 in this implementation. Therefore UNDEFINED can
 * be defined as 0 in situations where only unsigned numbers are desired.
 *****************************************************************************/

void
282
283
284
285
gimp_rgb_to_hwb (const GimpRGB *rgb,
		 gdouble       *hue,
		 gdouble       *whiteness,
		 gdouble       *blackness)
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
{
  /* RGB are each on [0, 1]. W and B are returned on [0, 1] and H is        */
  /* returned on [0, 6]. Exception: H is returned UNDEFINED if W ==  1 - B. */
  /* ====================================================================== */

  gdouble R = rgb->r, G = rgb->g, B = rgb->b, w, v, b, f;
  gint i;

  w = gimp_rgb_min (rgb);
  v = gimp_rgb_max (rgb);
  b = 1.0 - v;

  if (v == w)
    {
      *hue = GIMP_HSV_UNDEFINED;
      *whiteness = w;
      *blackness = b;
    }
  else
    {
      f = (R == w) ? G - B : ((G == w) ? B - R : R - G);
      i = (R == w) ? 3.0 : ((G == w) ? 5.0 : 1.0);
    
      *hue = (360.0 / 6.0) * (i - f / (v - w));
      *whiteness = w;
      *blackness = b;
    }
}

void
gimp_hwb_to_rgb (gdouble  hue,
		 gdouble  whiteness,
		 gdouble  blackness,
		 GimpRGB *rgb)
{
  /* H is given on [0, 6] or UNDEFINED. whiteness and
   * blackness are given on [0, 1].
   * RGB are each returned on [0, 1].
   */
  
  gdouble h = hue, w = whiteness, b = blackness, v, n, f;
  gint    i;

  h = 6.0 * h/ 360.0;

  v = 1.0 - b;
  if (h == GIMP_HSV_UNDEFINED)
    {
      rgb->r = v;
      rgb->g = v;
      rgb->b = v;
    }
  else
    {
      i = floor (h);
      f = h - i;

      if (i & 1)
	f = 1.0 - f;  /* if i is odd */

      n = w + f * (v - w);     /* linear interpolation between w and v */
    
      switch (i)
        {
          case 6:
          case 0: GIMP_RETURN_RGB (v, n, w);
            break;
          case 1: GIMP_RETURN_RGB (n, v, w);
            break;
          case 2: GIMP_RETURN_RGB (w, v, n);
            break;
          case 3: GIMP_RETURN_RGB (w, n, v);
            break;
          case 4: GIMP_RETURN_RGB (n, w, v);
            break;
          case 5: GIMP_RETURN_RGB (v, w, n);
            break;
        }
    }

}


/*  gint functions  */

Marc Lehmann's avatar
Marc Lehmann committed
371
void
372
373
374
gimp_rgb_to_hsv_int (gint *red,
		     gint *green,
		     gint *blue)
Marc Lehmann's avatar
Marc Lehmann committed
375
{
376
  gint    r, g, b;
377
378
379
  gdouble h, s, v;
  gint    min, max;
  gint    delta;
Marc Lehmann's avatar
Marc Lehmann committed
380
381
382

  h = 0.0;

383
384
385
  r = *red;
  g = *green;
  b = *blue;
Marc Lehmann's avatar
Marc Lehmann committed
386

387
  if (r > g)
Marc Lehmann's avatar
Marc Lehmann committed
388
    {
389
390
      max = MAX (r, b);
      min = MIN (g, b);
Marc Lehmann's avatar
Marc Lehmann committed
391
392
393
    }
  else
    {
394
395
      max = MAX (g, b);
      min = MIN (r, b);
Marc Lehmann's avatar
Marc Lehmann committed
396
397
398
399
400
    }

  v = max;

  if (max != 0)
401
    s = ((max - min) * 255) / (gdouble) max;
Marc Lehmann's avatar
Marc Lehmann committed
402
403
404
405
406
407
408
409
  else
    s = 0;

  if (s == 0)
    h = 0;
  else
    {
      delta = max - min;
410
411
412
413
414
415
      if (r == max)
	h = (g - b) / (gdouble) delta;
      else if (g == max)
	h = 2 + (b - r) / (gdouble) delta;
      else if (b == max)
	h = 4 + (r - g) / (gdouble) delta;
Marc Lehmann's avatar
Marc Lehmann committed
416
417
418
419
420
421
422
423
      h *= 42.5;

      if (h < 0)
	h += 255;
      if (h > 255)
	h -= 255;
    }

424
425
426
  *red   = ROUND (h);
  *green = ROUND (s);
  *blue  = ROUND (v);
Marc Lehmann's avatar
Marc Lehmann committed
427
428
429
}

void
430
431
432
gimp_hsv_to_rgb_int (gint *hue,
		     gint *saturation,
		     gint *value)
Marc Lehmann's avatar
Marc Lehmann committed
433
{
434
  gdouble h, s, v;
435
  gdouble f, p, q, t;
Marc Lehmann's avatar
Marc Lehmann committed
436

437
  if (*saturation == 0)
Marc Lehmann's avatar
Marc Lehmann committed
438
    {
439
440
441
      *hue        = *value;
      *saturation = *value;
      *value      = *value;
Marc Lehmann's avatar
Marc Lehmann committed
442
443
444
    }
  else
    {
445
446
447
      h = *hue * 6.0  / 255.0;
      s = *saturation / 255.0;
      v = *value      / 255.0;
Marc Lehmann's avatar
Marc Lehmann committed
448

449
      f = h - (gint) h;
450
451
452
      p = v * (1.0 - s);
      q = v * (1.0 - (s * f));
      t = v * (1.0 - (s * (1.0 - f)));
Marc Lehmann's avatar
Marc Lehmann committed
453

454
      switch ((gint) h)
Marc Lehmann's avatar
Marc Lehmann committed
455
456
	{
	case 0:
457
458
459
	  *hue        = ROUND (v * 255.0);
	  *saturation = ROUND (t * 255.0);
	  *value      = ROUND (p * 255.0);
Marc Lehmann's avatar
Marc Lehmann committed
460
	  break;
461

Marc Lehmann's avatar
Marc Lehmann committed
462
	case 1:
463
464
465
	  *hue        = ROUND (q * 255.0);
	  *saturation = ROUND (v * 255.0);
	  *value      = ROUND (p * 255.0);
Marc Lehmann's avatar
Marc Lehmann committed
466
	  break;
467

Marc Lehmann's avatar
Marc Lehmann committed
468
	case 2:
469
470
471
	  *hue        = ROUND (p * 255.0);
	  *saturation = ROUND (v * 255.0);
	  *value      = ROUND (t * 255.0);
Marc Lehmann's avatar
Marc Lehmann committed
472
	  break;
473

Marc Lehmann's avatar
Marc Lehmann committed
474
	case 3:
475
476
477
	  *hue        = ROUND (p * 255.0);
	  *saturation = ROUND (q * 255.0);
	  *value      = ROUND (v * 255.0);
Marc Lehmann's avatar
Marc Lehmann committed
478
	  break;
479

Marc Lehmann's avatar
Marc Lehmann committed
480
	case 4:
481
482
483
	  *hue        = ROUND (t * 255.0);
	  *saturation = ROUND (p * 255.0);
	  *value      = ROUND (v * 255.0);
Marc Lehmann's avatar
Marc Lehmann committed
484
	  break;
485

Marc Lehmann's avatar
Marc Lehmann committed
486
	case 5:
487
	case 6:
488
489
490
	  *hue        = ROUND (v * 255.0);
	  *saturation = ROUND (p * 255.0);
	  *value      = ROUND (q * 255.0);
Marc Lehmann's avatar
Marc Lehmann committed
491
492
493
494
495
496
	  break;
	}
    }
}

void
497
498
499
gimp_rgb_to_hls_int (gint *red,
		     gint *green,
		     gint *blue)
Marc Lehmann's avatar
Marc Lehmann committed
500
{
501
  gint    r, g, b;
502
503
504
  gdouble h, l, s;
  gint    min, max;
  gint    delta;
Marc Lehmann's avatar
Marc Lehmann committed
505

506
507
508
  r = *red;
  g = *green;
  b = *blue;
Marc Lehmann's avatar
Marc Lehmann committed
509

510
  if (r > g)
Marc Lehmann's avatar
Marc Lehmann committed
511
    {
512
513
      max = MAX (r, b);
      min = MIN (g, b);
Marc Lehmann's avatar
Marc Lehmann committed
514
515
516
    }
  else
    {
517
518
      max = MAX (g, b);
      min = MIN (r, b);
Marc Lehmann's avatar
Marc Lehmann committed
519
520
521
522
523
524
525
526
527
528
529
530
531
532
    }

  l = (max + min) / 2.0;

  if (max == min)
    {
      s = 0.0;
      h = 0.0;
    }
  else
    {
      delta = (max - min);

      if (l < 128)
533
	s = 255 * (gdouble) delta / (gdouble) (max + min);
Marc Lehmann's avatar
Marc Lehmann committed
534
      else
535
	s = 255 * (gdouble) delta / (gdouble) (511 - max - min);
Marc Lehmann's avatar
Marc Lehmann committed
536

537
538
539
540
      if (r == max)
	h = (g - b) / (gdouble) delta;
      else if (g == max)
	h = 2 + (b - r) / (gdouble) delta;
Marc Lehmann's avatar
Marc Lehmann committed
541
      else
542
	h = 4 + (r - g) / (gdouble) delta;
Marc Lehmann's avatar
Marc Lehmann committed
543
544
545
546
547
548
549
550
551

      h = h * 42.5;

      if (h < 0)
	h += 255;
      else if (h > 255)
	h -= 255;
    }

552
553
554
  *red   = ROUND (h);
  *green = ROUND (l);
  *blue  = ROUND (s);
Marc Lehmann's avatar
Marc Lehmann committed
555
556
}

557
gint
558
559
560
gimp_rgb_to_l_int (gint red,
		   gint green,
		   gint blue)
Marc Lehmann's avatar
Marc Lehmann committed
561
{
562
  gint min, max;
Marc Lehmann's avatar
Marc Lehmann committed
563
564
565

  if (red > green)
    {
566
567
      max = MAX (red,   blue);
      min = MIN (green, blue);
Marc Lehmann's avatar
Marc Lehmann committed
568
569
570
    }
  else
    {
571
572
      max = MAX (green, blue);
      min = MIN (red,   blue);
Marc Lehmann's avatar
Marc Lehmann committed
573
574
    }

575
  return ROUND ((max + min) / 2.0);
Marc Lehmann's avatar
Marc Lehmann committed
576
577
}

578
579
580
581
static gint
gimp_hls_value (gdouble n1,
		gdouble n2,
		gdouble hue)
Marc Lehmann's avatar
Marc Lehmann committed
582
{
583
  gdouble value;
Marc Lehmann's avatar
Marc Lehmann committed
584
585
586
587
588

  if (hue > 255)
    hue -= 255;
  else if (hue < 0)
    hue += 255;
589

Marc Lehmann's avatar
Marc Lehmann committed
590
591
592
593
594
595
596
597
598
  if (hue < 42.5)
    value = n1 + (n2 - n1) * (hue / 42.5);
  else if (hue < 127.5)
    value = n2;
  else if (hue < 170)
    value = n1 + (n2 - n1) * ((170 - hue) / 42.5);
  else
    value = n1;

599
  return ROUND (value * 255.0);
Marc Lehmann's avatar
Marc Lehmann committed
600
601
602
}

void
603
604
605
gimp_hls_to_rgb_int (gint *hue,
		     gint *lightness,
		     gint *saturation)
Marc Lehmann's avatar
Marc Lehmann committed
606
{
607
  gdouble h, l, s;
Marc Lehmann's avatar
Marc Lehmann committed
608

609
610
611
  h = *hue;
  l = *lightness;
  s = *saturation;
Marc Lehmann's avatar
Marc Lehmann committed
612

613
  if (s == 0)
Marc Lehmann's avatar
Marc Lehmann committed
614
615
    {
      /*  achromatic case  */
616
617
618
      *hue        = l;
      *lightness  = l;
      *saturation = l;
Marc Lehmann's avatar
Marc Lehmann committed
619
620
621
    }
  else
    {
622
623
      gdouble m1, m2;

624
625
      if (l < 128)
	m2 = (l * (255 + s)) / 65025.0;
Marc Lehmann's avatar
Marc Lehmann committed
626
      else
627
	m2 = (l + s - (l * s) / 255.0) / 255.0;
Marc Lehmann's avatar
Marc Lehmann committed
628

629
      m1 = (l / 127.5) - m2;
Marc Lehmann's avatar
Marc Lehmann committed
630
631

      /*  chromatic case  */
632
633
634
      *hue        = gimp_hls_value (m1, m2, h + 85);
      *lightness  = gimp_hls_value (m1, m2, h);
      *saturation = gimp_hls_value (m1, m2, h - 85);
Marc Lehmann's avatar
Marc Lehmann committed
635
636
637
638
    }
}

void
639
640
gimp_rgb_to_hsv4 (guchar  *rgb, 
		  gdouble *hue, 
641
642
		  gdouble *saturation, 
		  gdouble *value)
Marc Lehmann's avatar
Marc Lehmann committed
643
{
644
645
646
647
  gdouble red, green, blue;
  gdouble h, s, v;
  gdouble min, max;
  gdouble delta;
Marc Lehmann's avatar
Marc Lehmann committed
648
649
650
651
652
653
654
655
656

  red   = rgb[0] / 255.0;
  green = rgb[1] / 255.0;
  blue  = rgb[2] / 255.0;

  h = 0.0; /* Shut up -Wall */

  if (red > green)
    {
657
658
      max = MAX (red,   blue);
      min = MIN (green, blue);
Marc Lehmann's avatar
Marc Lehmann committed
659
660
661
    }
  else
    {
662
663
      max = MAX (green, blue);
      min = MIN (red,   blue);
Marc Lehmann's avatar
Marc Lehmann committed
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
    }

  v = max;

  if (max != 0.0)
    s = (max - min) / max;
  else
    s = 0.0;

  if (s == 0.0)
    h = 0.0;
  else
    {
      delta = max - min;

679
680
681
      if (delta == 0.0)
	delta = 1.0;

Marc Lehmann's avatar
Marc Lehmann committed
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
      if (red == max)
	h = (green - blue) / delta;
      else if (green == max)
	h = 2 + (blue - red) / delta;
      else if (blue == max)
	h = 4 + (red - green) / delta;

      h /= 6.0;

      if (h < 0.0)
	h += 1.0;
      else if (h > 1.0)
	h -= 1.0;
    }

697
698
699
  *hue        = h;
  *saturation = s;
  *value      = v;
Marc Lehmann's avatar
Marc Lehmann committed
700
701
702
}

void
703
gimp_hsv_to_rgb4 (guchar  *rgb, 
704
705
706
		  gdouble  hue,
		  gdouble  saturation,
		  gdouble  value)
Marc Lehmann's avatar
Marc Lehmann committed
707
{
708
  gdouble h, s, v;
709
  gdouble f, p, q, t;
Marc Lehmann's avatar
Marc Lehmann committed
710

711
  if (saturation == 0.0)
Marc Lehmann's avatar
Marc Lehmann committed
712
    {
713
714
715
      hue        = value;
      saturation = value;
      value      = value;
Marc Lehmann's avatar
Marc Lehmann committed
716
717
718
    }
  else
    {
719
720
721
      h = hue * 6.0;
      s = saturation;
      v = value;
Marc Lehmann's avatar
Marc Lehmann committed
722

723
724
      if (h == 6.0)
	h = 0.0;
Marc Lehmann's avatar
Marc Lehmann committed
725

726
727
728
729
      f = h - (gint) h;
      p = v * (1.0 - s);
      q = v * (1.0 - s * f);
      t = v * (1.0 - s * (1.0 - f));
Marc Lehmann's avatar
Marc Lehmann committed
730

731
      switch ((int) h)
Marc Lehmann's avatar
Marc Lehmann committed
732
733
	{
	case 0:
734
735
736
	  hue        = v;
	  saturation = t;
	  value      = p;
Marc Lehmann's avatar
Marc Lehmann committed
737
738
739
	  break;

	case 1:
740
741
742
	  hue        = q;
	  saturation = v;
	  value      = p;
Marc Lehmann's avatar
Marc Lehmann committed
743
744
745
	  break;

	case 2:
746
747
748
	  hue        = p;
	  saturation = v;
	  value      = t;
Marc Lehmann's avatar
Marc Lehmann committed
749
750
751
	  break;

	case 3:
752
753
754
	  hue        = p;
	  saturation = q;
	  value      = v;
Marc Lehmann's avatar
Marc Lehmann committed
755
756
757
	  break;

	case 4:
758
759
760
	  hue        = t;
	  saturation = p;
	  value      = v;
Marc Lehmann's avatar
Marc Lehmann committed
761
762
763
	  break;

	case 5:
764
765
766
	  hue        = v;
	  saturation = p;
	  value      = q;
Marc Lehmann's avatar
Marc Lehmann committed
767
768
769
770
	  break;
	}
    }

771
772
773
  rgb[0] = ROUND (hue        * 255.0);
  rgb[1] = ROUND (saturation * 255.0);
  rgb[2] = ROUND (value      * 255.0);
Marc Lehmann's avatar
Marc Lehmann committed
774
}