00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
#include <volume_io/internal_volume_io.h>
00016
#include <bicpl/vols.h>
00017
00018
#ifndef lint
00019
static char rcsid[] =
"$Header: /software/source//libraries/bicpl/Volumes/colour_coding.c,v 1.26 2000/12/15 19:55:07 stever Exp $";
00020
#endif
00021
00022
private void interpolate_colours(
00023
colour_point *p1,
00024
colour_point *p2,
00025 Real pos,
00026 Real *r,
00027 Real *g,
00028 Real *b,
00029 Real *a );
00030
00031
private void recreate_piecewise_function(
00032
colour_coding_struct *colour_coding,
00033 Colour_coding_types type,
00034 BOOLEAN set_user_defined );
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 public void initialize_colour_coding(
00054
colour_coding_struct *colour_coding,
00055 Colour_coding_types type,
00056 Colour under_colour,
00057 Colour over_colour,
00058 Real min_value,
00059 Real max_value )
00060 {
00061 colour_coding->
n_colour_points = 0;
00062 colour_coding->
user_defined_n_colour_points = 0;
00063
00064
set_colour_coding_type( colour_coding, type );
00065
set_colour_coding_min_max( colour_coding, min_value, max_value );
00066
set_colour_coding_under_colour( colour_coding, under_colour );
00067
set_colour_coding_over_colour( colour_coding, over_colour );
00068
00069
recreate_piecewise_function( colour_coding,
GRAY_SCALE,
TRUE );
00070 }
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 public void delete_colour_coding(
00086
colour_coding_struct *colour_coding )
00087 {
00088
if( colour_coding->
n_colour_points > 0 )
00089 FREE( colour_coding->
colour_points );
00090
if( colour_coding->
user_defined_n_colour_points > 0 )
00091 FREE( colour_coding->
user_defined_colour_points );
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 public void set_colour_coding_type(
00109
colour_coding_struct *colour_coding,
00110 Colour_coding_types type )
00111 {
00112 colour_coding->
type = type;
00113
00114
recreate_piecewise_function( colour_coding, type,
FALSE );
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 public Colour_coding_types get_colour_coding_type(
00131
colour_coding_struct *colour_coding )
00132 {
00133
return( colour_coding->
type );
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 public void set_colour_coding_min_max(
00152
colour_coding_struct *colour_coding,
00153 Real min_value,
00154 Real max_value )
00155 {
00156 colour_coding->
min_value = min_value;
00157 colour_coding->
max_value = max_value;
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 public void get_colour_coding_min_max(
00175
colour_coding_struct *colour_coding,
00176 Real *min_value,
00177 Real *max_value )
00178 {
00179 *min_value = colour_coding->
min_value;
00180 *max_value = colour_coding->
max_value;
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 public Colour
get_colour_coding_under_colour(
00197
colour_coding_struct *colour_coding )
00198 {
00199
return( colour_coding->
under_colour );
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 public void set_colour_coding_under_colour(
00217
colour_coding_struct *colour_coding,
00218 Colour under_colour )
00219 {
00220 colour_coding->
under_colour = under_colour;
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 public Colour
get_colour_coding_over_colour(
00237
colour_coding_struct *colour_coding )
00238 {
00239
return( colour_coding->
over_colour );
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 public void set_colour_coding_over_colour(
00257
colour_coding_struct *colour_coding,
00258 Colour over_colour )
00259 {
00260 colour_coding->
over_colour = over_colour;
00261
00262
00263
00264
00265
00266
if(
get_colour_coding_type( colour_coding ) ==
SINGLE_COLOUR_SCALE )
00267 {
00268
recreate_piecewise_function( colour_coding,
00269
get_colour_coding_type(colour_coding),
00270
FALSE );
00271 }
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 private void recreate_piecewise_function(
00290
colour_coding_struct *colour_coding,
00291 Colour_coding_types type,
00292 BOOLEAN set_user_defined )
00293 {
00294
static colour_point gray_scale_points[] =
00295 { {0.0, 0.0, 0.0, 0.0, 1.0,
RGB_SPACE },
00296 {1.0, 1.0, 1.0, 1.0, 1.0,
RGB_SPACE } };
00297
static colour_point hot_metal_points[] =
00298 { {0.0, 0.0, 0.0, 0.0, 1.0,
RGB_SPACE },
00299 {0.25, 0.5, 0.0, 0.0, 1.0,
RGB_SPACE },
00300 {0.5, 1.0, 0.5, 0.0, 1.0,
RGB_SPACE },
00301 {0.75, 1.0, 1.0, 0.5, 1.0,
RGB_SPACE },
00302 {1.0, 1.0, 1.0, 1.0, 1.0,
RGB_SPACE } };
00303
static colour_point spectral_points[] =
00304 { { 0.00, 0.0000,0.0000,0.0000, 1.0,
RGB_SPACE},
00305 { 0.05, 0.4667,0.0000,0.5333, 1.0,
RGB_SPACE},
00306 { 0.10, 0.5333,0.0000,0.6000, 1.0,
RGB_SPACE},
00307 { 0.15, 0.0000,0.0000,0.6667, 1.0,
RGB_SPACE},
00308 { 0.20, 0.0000,0.0000,0.8667, 1.0,
RGB_SPACE},
00309 { 0.25, 0.0000,0.4667,0.8667, 1.0,
RGB_SPACE},
00310 { 0.30, 0.0000,0.6000,0.8667, 1.0,
RGB_SPACE},
00311 { 0.35, 0.0000,0.6667,0.6667, 1.0,
RGB_SPACE},
00312 { 0.40, 0.0000,0.6667,0.5333, 1.0,
RGB_SPACE},
00313 { 0.45, 0.0000,0.6000,0.0000, 1.0,
RGB_SPACE},
00314 { 0.50, 0.0000,0.7333,0.0000, 1.0,
RGB_SPACE},
00315 { 0.55, 0.0000,0.8667,0.0000, 1.0,
RGB_SPACE},
00316 { 0.60, 0.0000,1.0000,0.0000, 1.0,
RGB_SPACE},
00317 { 0.65, 0.7333,1.0000,0.0000, 1.0,
RGB_SPACE},
00318 { 0.70, 0.9333,0.9333,0.0000, 1.0,
RGB_SPACE},
00319 { 0.75, 1.0000,0.8000,0.0000, 1.0,
RGB_SPACE},
00320 { 0.80, 1.0000,0.6000,0.0000, 1.0,
RGB_SPACE},
00321 { 0.85, 1.0000,0.0000,0.0000, 1.0,
RGB_SPACE},
00322 { 0.90, 0.8667,0.0000,0.0000, 1.0,
RGB_SPACE},
00323 { 0.95, 0.8000,0.0000,0.0000, 1.0,
RGB_SPACE},
00324 { 1.00, 0.8000,0.8000,0.8000, 1.0,
RGB_SPACE}
00325 };
00326
static colour_point red_points[] =
00327 { {0.0, 0.0, 0.0, 0.0, 1.0,
RGB_SPACE },
00328 {1.0, 1.0, 0.0, 0.0, 1.0,
RGB_SPACE } };
00329
static colour_point green_points[] =
00330 { {0.0, 0.0, 0.0, 0.0, 1.0,
RGB_SPACE },
00331 {1.0, 0.0, 1.0, 0.0, 1.0,
RGB_SPACE } };
00332
static colour_point blue_points[] =
00333 { {0.0, 0.0, 0.0, 0.0, 1.0,
RGB_SPACE },
00334 {1.0, 0.0, 0.0, 1.0, 1.0,
RGB_SPACE } };
00335
static colour_point contour_points[] =
00336 { {0.0, 0.0, 0.0, 0.3, 1.0,
RGB_SPACE },
00337 {0.166, 0.0, 0.0, 1.0, 1.0,
RGB_SPACE },
00338 {0.166, 0.0, 0.3, 0.3, 1.0,
RGB_SPACE },
00339 {0.333, 0.0, 1.0, 1.0, 1.0,
RGB_SPACE },
00340 {0.333, 0.0, 0.3, 0.0, 1.0,
RGB_SPACE },
00341 {0.5, 0.0, 1.0, 0.0, 1.0,
RGB_SPACE },
00342 {0.5, 0.3, 0.3, 0.0, 1.0,
RGB_SPACE },
00343 {0.666, 1.0, 1.0, 0.0, 1.0,
RGB_SPACE },
00344 {0.666, 0.3, 0.0, 0.0, 1.0,
RGB_SPACE },
00345 {0.833, 1.0, 0.0, 0.0, 1.0,
RGB_SPACE },
00346 {0.833, 0.3, 0.3, 0.3, 1.0,
RGB_SPACE },
00347 {1.0, 1.0, 1.0, 1.0, 1.0,
RGB_SPACE } };
00348
colour_point *points, **points_ptr;
00349
int p, n_points, *n_points_ptr;
00350 Real r, g, b, a;
00351
00352
switch( type )
00353 {
00354
case GRAY_SCALE:
00355
case SINGLE_COLOUR_SCALE:
00356 n_points = SIZEOF_STATIC_ARRAY( gray_scale_points );
00357 points = gray_scale_points;
00358
break;
00359
00360
case HOT_METAL:
00361 n_points = SIZEOF_STATIC_ARRAY( hot_metal_points );
00362 points = hot_metal_points;
00363
break;
00364
00365
case SPECTRAL:
00366 n_points = SIZEOF_STATIC_ARRAY( spectral_points );
00367 points = spectral_points;
00368
break;
00369
00370
case RED_COLOUR_MAP:
00371 n_points = SIZEOF_STATIC_ARRAY( red_points );
00372 points = red_points;
00373
break;
00374
00375
case GREEN_COLOUR_MAP:
00376 n_points = SIZEOF_STATIC_ARRAY( green_points );
00377 points = green_points;
00378
break;
00379
00380
case BLUE_COLOUR_MAP:
00381 n_points = SIZEOF_STATIC_ARRAY( blue_points );
00382 points = blue_points;
00383
break;
00384
00385
case CONTOUR_COLOUR_MAP:
00386 n_points = SIZEOF_STATIC_ARRAY( contour_points );
00387 points = contour_points;
00388
break;
00389
00390
case USER_DEFINED_COLOUR_MAP:
00391 n_points = colour_coding->
user_defined_n_colour_points;
00392 points = colour_coding->
user_defined_colour_points;
00393
break;
00394 }
00395
00396
if( set_user_defined )
00397 {
00398 n_points_ptr = &colour_coding->
user_defined_n_colour_points;
00399 points_ptr = &colour_coding->
user_defined_colour_points;
00400 }
00401
else
00402 {
00403 n_points_ptr = &colour_coding->
n_colour_points;
00404 points_ptr = &colour_coding->
colour_points;
00405 }
00406
00407
if( n_points != *n_points_ptr )
00408 {
00409
if( *n_points_ptr > 0 )
00410 FREE( *points_ptr );
00411
00412 *n_points_ptr = n_points;
00413 ALLOC( *points_ptr, n_points );
00414 }
00415
00416 for_less( p, 0, n_points )
00417 (*points_ptr)[p] = points[p];
00418
00419
if( type ==
SINGLE_COLOUR_SCALE )
00420 {
00421 r = get_Colour_r_0_1( colour_coding->
over_colour );
00422 g = get_Colour_g_0_1( colour_coding->
over_colour );
00423 b = get_Colour_b_0_1( colour_coding->
over_colour );
00424 a = get_Colour_a_0_1( colour_coding->
over_colour );
00425
00426 for_less( p, 0, n_points )
00427 {
00428 (*points_ptr)[p].r *= r;
00429 (*points_ptr)[p].g *= g;
00430 (*points_ptr)[p].b *= b;
00431 (*points_ptr)[p].a *= a;
00432 }
00433 }
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 public BOOLEAN
define_colour_coding_user_defined(
00455
colour_coding_struct *colour_code,
00456
int n_colours,
00457 Colour colours[],
00458 Real positions[],
00459 Colour_spaces interpolation_space )
00460 {
00461 Real pos;
00462
int p;
00463
00464
if( n_colours < 2 )
00465 {
00466 print(
"User defined colour coding must have at least 2 colours.\n" );
00467
return(
FALSE );
00468 }
00469
00470 for_less( p, 0, n_colours )
00471 {
00472
if( p > 0 && positions[p-1] > positions[p] )
00473 {
00474 print(
"User defined colour coding must have\n" );
00475 print(
"monotonic positions.\n" );
00476
return(
FALSE );
00477 }
00478 }
00479
00480
if( positions[0] == positions[n_colours-1] )
00481 {
00482 print(
00483
"User defined colour coding must have non-empty position range.\n" );
00484
return(
FALSE );
00485 }
00486
00487
if( colour_code->
user_defined_n_colour_points > 0 )
00488 FREE( colour_code->
user_defined_colour_points );
00489
00490 colour_code->
user_defined_n_colour_points = n_colours;
00491 ALLOC( colour_code->
user_defined_colour_points, n_colours );
00492
00493 for_less( p, 0, n_colours )
00494 {
00495
if( p == 0 )
00496 pos = 0.0;
00497
else if( p == n_colours - 1 )
00498 pos = 1.0;
00499
else
00500 pos = (positions[p] - positions[0]) /
00501 (positions[n_colours-1] - positions[0]);
00502
00503 colour_code->
user_defined_colour_points[p].
position = pos;
00504 colour_code->
user_defined_colour_points[p].
r =
00505 get_Colour_r_0_1(colours[p]);
00506 colour_code->
user_defined_colour_points[p].
g =
00507 get_Colour_g_0_1(colours[p]);
00508 colour_code->
user_defined_colour_points[p].
b =
00509 get_Colour_b_0_1(colours[p]);
00510 colour_code->
user_defined_colour_points[p].
a =
00511 get_Colour_a_0_1(colours[p]);
00512 colour_code->
user_defined_colour_points[p].
interpolation_space =
00513 interpolation_space;
00514 }
00515
00516
if(
get_colour_coding_type( colour_code ) ==
USER_DEFINED_COLOUR_MAP )
00517 {
00518
recreate_piecewise_function( colour_code,
00519
get_colour_coding_type(colour_code),
00520
FALSE );
00521 }
00522
00523
return(
TRUE );
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 public Colour
get_colour_code(
00541
colour_coding_struct *colour_coding,
00542 Real value )
00543 {
00544 Real pos, r, g, b, a;
00545
int i, n_points;
00546
colour_point *points;
00547
00548
if( colour_coding->
min_value <= colour_coding->
max_value )
00549 {
00550
if( value < colour_coding->
min_value )
00551
return( colour_coding->
under_colour );
00552
else if( value >= colour_coding->
max_value )
00553
return( colour_coding->
over_colour );
00554 }
00555
else
00556 {
00557
if( value > colour_coding->
min_value )
00558
return( colour_coding->
under_colour );
00559
else if( value <= colour_coding->
max_value )
00560
return( colour_coding->
over_colour );
00561 }
00562
00563 pos = (value - colour_coding->
min_value) /
00564 (colour_coding->
max_value - colour_coding->
min_value);
00565
00566 n_points = colour_coding->
n_colour_points;
00567
00568
if( n_points < 2 )
00569 {
00570 print_error(
"get_colour_code(): invalid piecewise function.\n" );
00571
return( make_rgba_Colour( 0, 0, 0, 0 ) );
00572 }
00573
00574 points = colour_coding->
colour_points;
00575
00576 for_less( i, 0, n_points-1 )
00577 {
00578
if( pos <= points[i+1].
position )
00579
break;
00580 }
00581
00582
interpolate_colours( &points[i], &points[i+1], pos, &r, &g, &b, &a );
00583
00584
return( make_rgba_Colour_0_1( r, g, b, a ) );
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 private void interpolate_colours(
00604
colour_point *p1,
00605
colour_point *p2,
00606 Real pos,
00607 Real *r,
00608 Real *g,
00609 Real *b,
00610 Real *a )
00611 {
00612 Real ratio, r0, g0, b0, a0, r1, g1, b1, a1;
00613
00614 ratio = (pos - p1->
position) / (p2->
position - p1->
position);
00615
00616 r0 = p1->
r;
00617 g0 = p1->
g;
00618 b0 = p1->
b;
00619 a0 = p1->
a;
00620
00621 r1 = p2->
r;
00622 g1 = p2->
g;
00623 b1 = p2->
b;
00624 a1 = p2->
a;
00625
00626
if( p1->
interpolation_space ==
HSL_SPACE )
00627 {
00628
rgb_to_hsl( r0, g0, b0, &r0, &g0, &b0 );
00629
rgb_to_hsl( r1, g1, b1, &r1, &g1, &b1 );
00630
00631
if( r0 == 1.0 && r1 < 0.5 )
00632 r0 = 0.0;
00633
if( r1 == 1.0 && r0 < 0.5 )
00634 r1 = 0.0;
00635 }
00636
00637 *r = r0 + (r1 - r0) * ratio;
00638 *g = g0 + (g1 - g0) * ratio;
00639 *b = b0 + (b1 - b0) * ratio;
00640 *a = a0 + (a1 - a0) * ratio;
00641
00642
if( p1->
interpolation_space ==
HSL_SPACE )
00643
hsl_to_rgb( *r, *g, *b, r, g, b );
00644 }