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/render.c,v 1.43 2000/06/20 14:58:58 neelin Exp $";
00020
#endif
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 private void clip(
00040 Real left_edge,
00041 Real right_edge,
00042 Real origin,
00043 Real delta,
00044 Real *t_min,
00045 Real *t_max )
00046 {
00047 Real t;
00048
00049
if( delta == 0.0 )
00050 {
00051
if( origin < left_edge || origin >= right_edge )
00052 {
00053 *t_min = 1.0;
00054 *t_max = 0.0;
00055 }
00056 }
00057
else if( delta > 0.0 )
00058 {
00059 t = (left_edge - origin) / delta;
00060
if( t > *t_min )
00061 *t_min = t;
00062
00063 t = (right_edge - origin) / delta;
00064
if( t < *t_max )
00065 *t_max = t;
00066 }
00067
else
00068 {
00069 t = (left_edge - origin) / delta;
00070
if( t < *t_max )
00071 *t_max = t;
00072
00073 t = (right_edge - origin) / delta;
00074
if( t > *t_min )
00075 *t_min = t;
00076 }
00077 }
00078
00079 typedef struct
00080
{
00081 int **x_offsets1;
00082 int **
y_offsets1;
00083 int ***which_x_offsets1;
00084 void **
start_slices1;
00085 int **
row_offsets1;
00086
00087 int **x_offsets2;
00088 int **y_offsets2;
00089 int ***which_x_offsets2;
00090 void **start_slices2;
00091 int **row_offsets2;
00092
00093 int *
start_x;
00094 int *
end_x;
00095
00096 int x_size1_alloced;
00097 int y_size1_alloced;
00098 int total_cases1_alloced;
00099 int n_slices1_alloced;
00100
00101 int x_size2_alloced;
00102 int y_size2_alloced;
00103 int total_cases2_alloced;
00104 int n_slices2_alloced;
00105 }
00106
render_storage_struct;
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 public void *
initialize_render_storage(
void )
00123 {
00124
render_storage_struct *store;
00125
void *void_ptr;
00126
00127 ALLOC( store, 1 );
00128
00129 store->
x_size1_alloced = 0;
00130 store->
y_size1_alloced = 0;
00131 store->
total_cases1_alloced = 0;
00132 store->
n_slices1_alloced = 0;
00133
00134 store->
x_size2_alloced = 0;
00135 store->
y_size2_alloced = 0;
00136 store->
total_cases2_alloced = 0;
00137 store->
n_slices2_alloced = 0;
00138
00139 void_ptr = (
void *) store;
00140
00141
return( void_ptr );
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 public void delete_render_storage(
00158
void *ptr )
00159 {
00160
render_storage_struct *store;
00161
00162 store = (
render_storage_struct *) ptr;
00163
00164
if( store->
total_cases1_alloced > 0 && store->
x_size1_alloced > 0 )
00165 FREE2D( store->
x_offsets1 );
00166
00167
if( store->
n_slices1_alloced > 0 && store->
y_size1_alloced > 0 )
00168 {
00169 FREE2D( store->
y_offsets1 );
00170 FREE2D( store->
which_x_offsets1 );
00171 }
00172
00173
if( store->
n_slices1_alloced > 0 )
00174 {
00175 FREE( store->
start_slices1 );
00176 FREE( store->
row_offsets1 );
00177 }
00178
00179
if( store->
total_cases2_alloced > 0 && store->
x_size2_alloced > 0 )
00180 FREE2D( store->
x_offsets2 );
00181
00182
if( store->
n_slices2_alloced > 0 && store->
y_size2_alloced > 0 )
00183 {
00184 FREE2D( store->
y_offsets2 );
00185 FREE2D( store->
which_x_offsets2 );
00186 }
00187
00188
if( store->
n_slices2_alloced > 0 )
00189 {
00190 FREE( store->
start_slices2 );
00191 FREE( store->
row_offsets2 );
00192 }
00193
00194
if( store->
y_size1_alloced > 0 )
00195 {
00196 FREE( store->
start_x );
00197 FREE( store->
end_x );
00198 }
00199
00200 FREE( store );
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 public void render_volume_to_slice(
00217
int n_dims1,
00218
int sizes1[],
00219
void *volume_data1,
00220 Data_types volume1_type,
00221
int n_slices1,
00222 Real weights1[],
00223
int strides1[],
00224 Real **origins1,
00225 Real x_axis1[],
00226 Real y_axis1[],
00227
int n_dims2,
00228
int sizes2[],
00229
void *volume_data2,
00230 Data_types volume2_type,
00231
int n_slices2,
00232 Real weights2[],
00233
int strides2[],
00234 Real **origins2,
00235 Real x_axis2[],
00236 Real y_axis2[],
00237
int x_pixel_start,
00238
int x_pixel_end,
00239
int y_pixel_start,
00240
int y_pixel_end,
00241
unsigned short **cmode_colour_map,
00242 Colour **rgb_colour_map,
00243 Colour empty_colour,
00244
void *render_storage,
00245
pixels_struct *pixels )
00246 {
00247
int i, c, p, total_cases1, total_cases2, case_index, case_multiplier;
00248
int max_offset, offset, int_start;
00249
int s, x,
y, n_cases1[MAX_DIMENSIONS], n_cases2[MAX_DIMENSIONS];
00250
int **x_offsets1, **
y_offsets1, *
start_x, *
end_x;
00251
int **x_offsets2, **y_offsets2;
00252
int ***which_x_offsets1, ***which_x_offsets2;
00253
int remainder_case, x_size, y_size;
00254
int **
row_offsets1, **row_offsets2;
00255
int x_left, x_right, n_non_zero;
00256
void **
start_slices1, **start_slices2;
00257 Real start_c, x_start, x_end, remainder, tmp_origin[MAX_DIMENSIONS];
00258 Real remainder_offset, left_edge, right_edge, delta;
00259
render_storage_struct *store;
00260
static int max_cases[MAX_DIMENSIONS] = { 10, 10, 4, 3, 3 };
00261
int new_total_cases1, new_x_size1, new_y_size1, new_n_slices1;
00262
int new_total_cases2, new_x_size2, new_y_size2, new_n_slices2;
00263
00264
if( render_storage == NULL )
00265 store = (
render_storage_struct *)
initialize_render_storage();
00266
else
00267 store = (
render_storage_struct *) render_storage;
00268
00269 x_size = pixels->
x_size;
00270 y_size = pixels->
y_size;
00271
00272 n_non_zero = 0;
00273 for_less( c, 0, n_dims1 )
00274 {
00275
if( y_axis1[c] != 0.0 )
00276 ++n_non_zero;
00277 }
00278
00279 total_cases1 = 1;
00280 for_less( c, 0, n_dims1 )
00281 {
00282 delta = FABS( y_axis1[c] );
00283
if( delta == 0.0 || n_non_zero == 1 )
00284 n_cases1[c] = 1;
00285
else if( delta <= 1.0 / (Real) max_cases[n_dims1-1] )
00286 n_cases1[c] = max_cases[n_dims1-1];
00287
else
00288 {
00289 n_cases1[c] = (
int) (1.0 / delta);
00290
if( n_cases1[c] < 1 )
00291 n_cases1[c] = 1;
00292
else if( n_cases1[c] > max_cases[n_dims1-1] )
00293 n_cases1[c] = max_cases[n_dims1-1];
00294 }
00295
00296 total_cases1 *= n_cases1[c];
00297 }
00298
00299 new_total_cases1 = MAX( total_cases1, store->
total_cases1_alloced );
00300 new_x_size1 = MAX( x_size, store->
x_size1_alloced );
00301 new_y_size1 = MAX( y_size, store->
y_size1_alloced );
00302 new_n_slices1 = MAX(
n_slices1, store->
n_slices1_alloced );
00303
00304
if( new_total_cases1 > store->
total_cases1_alloced ||
00305 new_x_size1 > store->
x_size1_alloced )
00306 {
00307
if( store->
total_cases1_alloced > 0 && store->
x_size1_alloced > 0 )
00308 FREE2D( store->
x_offsets1 );
00309 ALLOC2D( store->
x_offsets1, new_total_cases1, new_x_size1 );
00310 }
00311
00312
if( new_n_slices1 > store->
n_slices1_alloced ||
00313 new_y_size1 > store->
y_size1_alloced )
00314 {
00315
if( store->
n_slices1_alloced > 0 && store->
y_size1_alloced > 0 )
00316 {
00317 FREE2D( store->
y_offsets1 );
00318 FREE2D( store->
which_x_offsets1 );
00319 }
00320 ALLOC2D( store->
y_offsets1, new_n_slices1, new_y_size1 );
00321 ALLOC2D( store->
which_x_offsets1, new_n_slices1, new_y_size1 );
00322 }
00323
00324
00325
if( new_n_slices1 > store->
n_slices1_alloced )
00326 {
00327 SET_ARRAY_SIZE( store->
start_slices1, store->
n_slices1_alloced,
00328 new_n_slices1, DEFAULT_CHUNK_SIZE );
00329 SET_ARRAY_SIZE( store->
row_offsets1, store->
n_slices1_alloced,
00330 new_n_slices1, DEFAULT_CHUNK_SIZE );
00331 }
00332
00333
if( new_y_size1 > store->
y_size1_alloced )
00334 {
00335 SET_ARRAY_SIZE( store->
start_x, store->
y_size1_alloced,
00336 new_y_size1, DEFAULT_CHUNK_SIZE );
00337 SET_ARRAY_SIZE( store->
end_x, store->
y_size1_alloced,
00338 new_y_size1, DEFAULT_CHUNK_SIZE );
00339 }
00340
00341 store->
total_cases1_alloced = new_total_cases1;
00342 store->
n_slices1_alloced = new_n_slices1;
00343 store->
x_size1_alloced = new_x_size1;
00344 store->
y_size1_alloced = new_y_size1;
00345
00346 x_offsets1 = store->
x_offsets1;
00347
y_offsets1 = store->
y_offsets1;
00348 which_x_offsets1 = store->
which_x_offsets1;
00349
start_slices1 = store->
start_slices1;
00350
00351
start_x = store->
start_x;
00352
end_x = store->
end_x;
00353
row_offsets1 = store->
row_offsets1;
00354
00355
if( volume_data2 != (
void *) NULL )
00356 {
00357 n_non_zero = 0;
00358 for_less( c, 0, n_dims1 )
00359 {
00360
if( y_axis1[c] != 0.0 )
00361 ++n_non_zero;
00362 }
00363
00364 total_cases2 = 1;
00365 for_less( c, 0, n_dims2 )
00366 {
00367 delta = FABS( y_axis2[c] );
00368
if( delta == 0.0 || n_non_zero == 1 )
00369 n_cases2[c] = 1;
00370
else if( delta <= 1.0 / (Real) max_cases[n_dims2-1] )
00371 n_cases2[c] = max_cases[n_dims2-1];
00372
else
00373 {
00374 n_cases2[c] = (
int) (1.0 / delta);
00375
if( n_cases2[c] < 1 )
00376 n_cases2[c] = 1;
00377
else if( n_cases2[c] > max_cases[n_dims2-1] )
00378 n_cases2[c] = max_cases[n_dims2-1];
00379 }
00380
00381 total_cases2 *= n_cases2[c];
00382 }
00383
00384 new_total_cases2 = MAX( total_cases2, store->
total_cases2_alloced );
00385 new_x_size2 = MAX( x_size, store->
x_size2_alloced );
00386 new_y_size2 = MAX( y_size, store->
y_size2_alloced );
00387 new_n_slices2 = MAX( n_slices2, store->
n_slices2_alloced );
00388
00389
if( new_total_cases2 > store->
total_cases2_alloced ||
00390 new_x_size2 > store->
x_size2_alloced )
00391 {
00392
if( store->
total_cases2_alloced > 0 && store->
x_size2_alloced > 0 )
00393 FREE2D( store->
x_offsets2 );
00394 ALLOC2D( store->
x_offsets2, new_total_cases2, new_x_size2 );
00395 }
00396
00397
if( new_n_slices2 > store->
n_slices2_alloced ||
00398 new_y_size2 > store->
y_size2_alloced )
00399 {
00400
if( store->
n_slices2_alloced > 0 && store->
y_size2_alloced > 0 )
00401 {
00402 FREE2D( store->
y_offsets2 );
00403 FREE2D( store->
which_x_offsets2 );
00404 }
00405 ALLOC2D( store->
y_offsets2, new_n_slices2, new_y_size2 );
00406 ALLOC2D( store->
which_x_offsets2, new_n_slices2, new_y_size2 );
00407 }
00408
00409
if( new_n_slices2 > store->
n_slices2_alloced )
00410 {
00411 SET_ARRAY_SIZE( store->
start_slices2, store->
n_slices2_alloced,
00412 new_n_slices2, DEFAULT_CHUNK_SIZE );
00413 SET_ARRAY_SIZE( store->
row_offsets2, store->
n_slices2_alloced,
00414 new_n_slices2, DEFAULT_CHUNK_SIZE );
00415 }
00416
00417 store->
total_cases2_alloced = new_total_cases2;
00418 store->
n_slices2_alloced = new_n_slices2;
00419 store->
x_size2_alloced = new_x_size2;
00420 store->
y_size2_alloced = new_y_size2;
00421
00422 x_offsets2 = store->
x_offsets2;
00423 y_offsets2 = store->
y_offsets2;
00424 which_x_offsets2 = store->
which_x_offsets2;
00425 start_slices2 = store->
start_slices2;
00426 row_offsets2 = store->
row_offsets2;
00427 }
00428
00429 for_less( i, 0, total_cases1 )
00430 {
00431 p = i;
00432 for_less( c, 0, n_dims1 )
00433 {
00434 case_index = p % n_cases1[c];
00435
if( y_axis1[c] == 0.0 &&
n_slices1 == n_cases1[c] )
00436 tmp_origin[c] = FRACTION( origins1[case_index][c] + 0.5 );
00437
else
00438 tmp_origin[c] = ((Real) case_index + 0.5) / (Real) n_cases1[c];
00439 p /= n_cases1[c];
00440 }
00441
00442 for_inclusive( x, x_pixel_start, x_pixel_end )
00443 {
00444 offset = 0;
00445 for_less( c, 0, n_dims1 )
00446 {
00447 start_c = tmp_origin[c] + (Real) x * x_axis1[c];
00448 offset += strides1[c] * FLOOR( start_c );
00449 }
00450 x_offsets1[i][x] = offset;
00451 }
00452 }
00453
00454
if( volume_data2 != (
void *) NULL )
00455 {
00456 for_less( i, 0, total_cases2 )
00457 {
00458 p = i;
00459 for_less( c, 0, n_dims2 )
00460 {
00461 case_index = p % n_cases2[c];
00462
if( y_axis2[c] == 0.0 && n_slices2 == n_cases2[c] )
00463 tmp_origin[c] = FRACTION( origins2[case_index][c] + 0.5 );
00464
else
00465 tmp_origin[c] = ((Real) case_index + 0.5) /
00466 (Real) n_cases2[c];
00467 p /= n_cases2[c];
00468 }
00469
00470 for_inclusive( x, x_pixel_start, x_pixel_end )
00471 {
00472 offset = 0;
00473 for_less( c, 0, n_dims2 )
00474 {
00475 start_c = tmp_origin[c] + (Real) x * x_axis2[c];
00476 offset += strides2[c] * FLOOR( start_c );
00477 }
00478 x_offsets2[i][x] = offset;
00479 }
00480 }
00481 }
00482
00483 for_inclusive(
y, y_pixel_start, y_pixel_end )
00484 {
00485 x_start = 0.0;
00486 x_end = (Real) (x_size - 1);
00487 for_less( s, 0,
n_slices1 )
00488 {
00489 offset = 0;
00490 case_index = 0;
00491 case_multiplier = 1;
00492 for_less( c, 0, n_dims1 )
00493 {
00494 start_c = origins1[s][c] + (Real)
y * y_axis1[c] + 0.5;
00495 int_start = FLOOR( start_c );
00496
00497
if( y_axis1[c] == 0.0 &&
n_slices1 == n_cases1[c] )
00498 {
00499 remainder_case = s;
00500 remainder_offset = 0.0;
00501 }
00502
else
00503 {
00504 remainder = start_c - (Real) int_start;
00505 remainder_case = (
int) (remainder * (Real) n_cases1[c]);
00506 remainder_offset = remainder -
00507 ((Real) remainder_case + 0.5)/ (Real) n_cases1[c];
00508 }
00509
00510 case_index += case_multiplier * remainder_case;
00511 case_multiplier *= n_cases1[c];
00512 offset += strides1[c] * int_start;
00513
00514 left_edge = 0.0;
00515 right_edge = (Real) sizes1[c];
00516
00517
if( remainder_offset < 0.0 )
00518 right_edge += remainder_offset;
00519
else
00520 left_edge += remainder_offset;
00521
00522
clip( left_edge, right_edge, start_c, x_axis1[c],
00523 &x_start, &x_end );
00524 }
00525
00526
y_offsets1[s][
y] = offset;
00527 which_x_offsets1[s][
y] = x_offsets1[case_index];
00528 }
00529
00530
if( volume_data2 != (
void *) NULL )
00531 {
00532 for_less( s, 0, n_slices2 )
00533 {
00534 offset = 0;
00535 case_index = 0;
00536 case_multiplier = 1;
00537 for_less( c, 0, n_dims2 )
00538 {
00539 start_c = origins2[s][c] + (Real)
y * y_axis2[c] + 0.5;
00540 int_start = FLOOR( start_c );
00541
00542
if( y_axis2[c] == 0.0 && n_slices2 == n_cases2[c] )
00543 {
00544 remainder_case = s;
00545 remainder_offset = 0.0;
00546 }
00547
else
00548 {
00549 remainder = start_c - (Real) int_start;
00550 remainder_case = (
int) (remainder * (Real) n_cases2[c]);
00551 remainder_offset = remainder -
00552 ((Real) remainder_case + 0.5)/ (Real) n_cases2[c];
00553 }
00554
00555 case_index += case_multiplier * remainder_case;
00556 case_multiplier *= n_cases2[c];
00557 offset += strides2[c] * int_start;
00558
00559 left_edge = 0.0;
00560 right_edge = (Real) sizes2[c];
00561
00562
if( remainder_offset < 0.0 )
00563 right_edge += remainder_offset;
00564
else
00565 left_edge += remainder_offset;
00566
00567
clip( left_edge, right_edge, start_c, x_axis2[c],
00568 &x_start, &x_end );
00569 }
00570
00571 y_offsets2[s][
y] = offset;
00572 which_x_offsets2[s][
y] = x_offsets2[case_index];
00573 }
00574 }
00575
00576
start_x[
y] = CEILING( x_start );
00577
end_x[
y] = FLOOR( x_end );
00578
00579
if(
start_x[
y] > x_size )
00580
start_x[
y] = x_size;
00581
if(
end_x[
y] < 0 )
00582
end_x[
y] = 0;
00583
if(
start_x[
y] >
end_x[
y] + 1 )
00584
start_x[
y] =
end_x[
y] + 1;
00585 }
00586
00587 for_inclusive(
y, y_pixel_start, y_pixel_end )
00588 {
00589 for_less( s, 0,
n_slices1 )
00590
row_offsets1[s] = which_x_offsets1[s][
y];
00591
00592
if( volume_data2 != (
void *) NULL )
00593 {
00594 for_less( s, 0, n_slices2 )
00595 row_offsets2[s] = which_x_offsets2[s][
y];
00596 }
00597
00598 x_left = MAX( x_pixel_start,
start_x[
y] );
00599 x_right = MIN( x_pixel_end,
end_x[
y] );
00600
00601
00602
00603
00604
00605 max_offset = 1;
00606 for_less( c, 0, n_dims1 ) {
00607 max_offset *= sizes1[c];
00608 }
00609 for_less( s, 0,
n_slices1 ) {
00610 offset =
y_offsets1[s][
y] +
row_offsets1[s][x_left];
00611
if ((offset < 0) || (offset >= max_offset))
00612 x_left++;
00613 offset =
y_offsets1[s][
y] +
row_offsets1[s][x_right];
00614
if ((offset < 0) || (offset >= max_offset))
00615 x_right--;
00616 }
00617
if (volume_data2 != NULL) {
00618 max_offset = 1;
00619 for_less( c, 0, n_dims2 ) {
00620 max_offset *= sizes2[c];
00621 }
00622 for_less( s, 0, n_slices2 ) {
00623 offset = y_offsets2[s][
y] + row_offsets2[s][x_left];
00624
if ((offset < 0) || (offset >= max_offset))
00625 x_left++;
00626 offset = y_offsets2[s][
y] + row_offsets2[s][x_right];
00627
if ((offset < 0) || (offset >= max_offset))
00628 x_right--;
00629 }
00630 }
00631
00632
if( x_left <= x_right )
00633 {
00634
render_one_row(
volume_data1, volume1_type,
00635
y, x_left, x_right,
00636
y_offsets1,
row_offsets1,
start_slices1,
00637
n_slices1,
weights1,
00638 volume_data2, volume2_type,
00639 y_offsets2, row_offsets2, start_slices2,
00640 n_slices2, weights2,
00641 cmode_colour_map,
00642
rgb_colour_map,
00643 pixels );
00644 }
00645
00646
if( pixels->
pixel_type ==
RGB_PIXEL )
00647 {
00648 Colour *pixel_ptr;
00649
00650 pixel_ptr = &pixels->
data.pixels_rgb[IJ(
y,x_pixel_start,x_size)];
00651
00652 for_less( x, x_pixel_start,
start_x[
y] )
00653 {
00654 *pixel_ptr = empty_colour;
00655 ++pixel_ptr;
00656 }
00657
00658 pixel_ptr = &pixels->
data.pixels_rgb[IJ(
y,
end_x[
y]+1,x_size)];
00659 for_less( x,
end_x[
y]+1, x_pixel_end+1 )
00660 {
00661 *pixel_ptr = empty_colour;
00662 ++pixel_ptr;
00663 }
00664 }
00665
else
00666 {
00667
unsigned short *pixel_ptr;
00668
00669 pixel_ptr = &pixels->
data.pixels_16bit_colour_index
00670 [IJ(
y,x_pixel_start,x_size)];
00671 for_less( x, x_pixel_start,
start_x[
y] )
00672 {
00673 *pixel_ptr = (
unsigned short) empty_colour;
00674 ++pixel_ptr;
00675 }
00676
00677 pixel_ptr = &pixels->
data.pixels_16bit_colour_index
00678 [IJ(
y,
end_x[
y]+1,x_size)];
00679 for_less( x,
end_x[
y]+1, x_pixel_end+1 )
00680 {
00681 *pixel_ptr = (
unsigned short) empty_colour;
00682 ++pixel_ptr;
00683 }
00684 }
00685 }
00686
00687
if( render_storage == NULL )
00688
delete_render_storage( (
void *) store );
00689 }