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/objects.h>
00017
#include <bicpl/geom.h>
00018
#include <bicpl/trans.h>
00019
00020
#ifndef lint
00021
static char rcsid[] =
"$Header: /software/source//libraries/bicpl/Objects/pixels.c,v 1.26 2000/02/06 15:30:45 stever Exp $";
00022
#endif
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 public void initialize_pixels(
00044
pixels_struct *pixels,
00045
int x_position,
00046
int y_position,
00047
int x_size,
00048
int y_size,
00049 Real x_zoom,
00050 Real y_zoom,
00051 Pixel_types pixel_type )
00052 {
00053
int n_alloced;
00054
00055 n_alloced = 0;
00056
00057 pixels->
pixel_type = pixel_type;
00058 pixels->
x_size = -1;
00059 pixels->
y_size = -1;
00060 pixels->
x_position = x_position;
00061 pixels->
y_position = y_position;
00062 pixels->
x_zoom = x_zoom;
00063 pixels->
y_zoom = y_zoom;
00064
00065
modify_pixels_size( &n_alloced, pixels, x_size, y_size, pixel_type );
00066 }
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 public void delete_pixels(
pixels_struct *pixels )
00082 {
00083
if( pixels->
x_size > 0 && pixels->
y_size > 0 )
00084 {
00085
switch( pixels->
pixel_type )
00086 {
00087
case COLOUR_INDEX_8BIT_PIXEL:
00088 FREE( pixels->
data.pixels_8bit_colour_index );
00089
break;
00090
00091
case COLOUR_INDEX_16BIT_PIXEL:
00092 FREE( pixels->
data.pixels_16bit_colour_index );
00093
break;
00094
00095
case RGB_PIXEL:
00096 FREE( pixels->
data.pixels_rgb );
00097
break;
00098 }
00099 }
00100
00101 pixels->
x_size = 0;
00102 pixels->
y_size = 0;
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 public void modify_pixels_size(
00123
int *n_pixels_alloced,
00124
pixels_struct *pixels,
00125
int x_size,
00126
int y_size,
00127 Pixel_types pixel_type )
00128 {
00129
int new_n_pixels;
00130 Colour *tmp_int_ptr;
00131
00132
if( pixel_type != pixels->
pixel_type )
00133 {
00134
if( *n_pixels_alloced > 0 )
00135
delete_pixels( pixels );
00136 *n_pixels_alloced = 0;
00137 pixels->
pixel_type = pixel_type;
00138 }
00139
00140
if( x_size > 0 && y_size > 0 )
00141 new_n_pixels = x_size * y_size;
00142
else
00143 new_n_pixels = 0;
00144
00145 pixels->
x_size = x_size;
00146 pixels->
y_size = y_size;
00147
00148
00149
00150
if( new_n_pixels > 0 && new_n_pixels <= *n_pixels_alloced )
00151
return;
00152
00153
switch( pixel_type )
00154 {
00155
case COLOUR_INDEX_8BIT_PIXEL:
00156 tmp_int_ptr = (Colour *) (
void *)
00157 pixels->
data.pixels_8bit_colour_index;
00158
00159 SET_ARRAY_SIZE( tmp_int_ptr, (*n_pixels_alloced + 3) / 4,
00160 (new_n_pixels + 3) / 4, DEFAULT_CHUNK_SIZE );
00161 pixels->
data.pixels_8bit_colour_index = (
unsigned char *)
00162 ((
void *) tmp_int_ptr );
00163
break;
00164
00165
case COLOUR_INDEX_16BIT_PIXEL:
00166 tmp_int_ptr = (Colour *) (
void *)
00167 pixels->
data.pixels_16bit_colour_index;
00168 SET_ARRAY_SIZE( tmp_int_ptr, (*n_pixels_alloced + 1) / 2,
00169 (new_n_pixels + 1) / 2, DEFAULT_CHUNK_SIZE );
00170 pixels->
data.pixels_16bit_colour_index = (
unsigned short *)
00171 ((
void *) tmp_int_ptr );
00172
break;
00173
00174
case RGB_PIXEL:
00175 SET_ARRAY_SIZE( pixels->
data.pixels_rgb, *n_pixels_alloced,
00176 new_n_pixels, DEFAULT_CHUNK_SIZE );
00177
break;
00178 }
00179
00180 *n_pixels_alloced = new_n_pixels;
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 public void convert_pixels24_to_pixels8(
00197
pixels_struct *pixels_rgb,
00198
pixels_struct *pixels_8 )
00199 {
00200
int x,
y;
00201
00202
initialize_pixels( pixels_8, pixels_rgb->
x_position, pixels_rgb->
y_position,
00203 pixels_rgb->
x_size, pixels_rgb->
y_size,
00204 pixels_rgb->
x_zoom, pixels_rgb->
y_zoom,
00205
COLOUR_INDEX_8BIT_PIXEL );
00206
00207 for_less( x, 0, pixels_rgb->
x_size )
00208 {
00209 for_less(
y, 0, pixels_rgb->
y_size )
00210 {
00211
PIXEL_COLOUR_INDEX_8(*pixels_8,x,
y) =
00212 (
unsigned char)
convert_rgb_pixel_to_8bit_lookup(
00213
PIXEL_RGB_COLOUR(*pixels_rgb,x,
y) );
00214 }
00215 }
00216 }
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 public void convert_pixels24_to_index8(
00235
pixels_struct *pixels_rgb,
00236
pixels_struct *pixels_8,
00237
int n_colours,
00238 Colour colour_table[] )
00239 {
00240 Colour col;
00241
int x,
y;
00242
00243
initialize_pixels( pixels_8, pixels_rgb->
x_position, pixels_rgb->
y_position,
00244 pixels_rgb->
x_size, pixels_rgb->
y_size,
00245 pixels_rgb->
x_zoom, pixels_rgb->
y_zoom,
00246
COLOUR_INDEX_8BIT_PIXEL );
00247
00248 for_less( x, 0, pixels_rgb->
x_size )
00249 {
00250 for_less(
y, 0, pixels_rgb->
y_size )
00251 {
00252 col =
PIXEL_RGB_COLOUR(*pixels_rgb,x,
y);
00253
00254
PIXEL_COLOUR_INDEX_8(*pixels_8,x,
y) =
00255 (
unsigned char)
find_closest_colour( get_Colour_r(col),
00256 get_Colour_g(col),
00257 get_Colour_b(col),
00258 n_colours, colour_table );
00259 }
00260 }
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 public void convert_index8_to_pixels24(
00278
pixels_struct *pixels_8,
00279 Colour colour_table[],
00280
pixels_struct *pixels_rgb )
00281 {
00282
int x,
y;
00283
00284
initialize_pixels( pixels_rgb, pixels_8->
x_position, pixels_8->
y_position,
00285 pixels_8->
x_size, pixels_8->
y_size,
00286 pixels_8->
x_zoom, pixels_8->
y_zoom,
RGB_PIXEL );
00287
00288 for_less( x, 0, pixels_rgb->
x_size )
00289 {
00290 for_less(
y, 0, pixels_rgb->
y_size )
00291 {
00292
PIXEL_RGB_COLOUR(*pixels_rgb,x,
y) = colour_table[
00293 (
int)
PIXEL_COLOUR_INDEX_8(*pixels_8,x,
y)];
00294 }
00295 }
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 public void convert_pixels24_to_gray_scale(
00312
pixels_struct *pixels_rgb,
00313
pixels_struct *pixels_8 )
00314 {
00315
int x,
y;
00316
00317
initialize_pixels( pixels_8, 0, 0, pixels_rgb->
x_size, pixels_rgb->
y_size,
00318 1.0, 1.0,
00319
COLOUR_INDEX_8BIT_PIXEL );
00320
00321 for_less( x, 0, pixels_rgb->
x_size )
00322 {
00323 for_less(
y, 0, pixels_rgb->
y_size )
00324 {
00325
PIXEL_COLOUR_INDEX_8(*pixels_8,x,
y) = (
unsigned char)
00326
get_Colour_luminance(
PIXEL_RGB_COLOUR(*pixels_rgb,x,
y) );
00327 }
00328 }
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 public void convert_pixels24_to_dithered(
00348
pixels_struct *pixels_rgb,
00349
pixels_struct *pixels_8,
00350
int n_colours,
00351 Colour colour_table[] )
00352 {
00353
int x,
y, dir, error_row, c, comp[3], used[3];
00354
int first_x, last_x, ind, one, three, five, seven, error;
00355 Colour col;
00356
short ***errors;
00357
00358
initialize_pixels( pixels_8, 0, 0, pixels_rgb->
x_size, pixels_rgb->
y_size,
00359 1.0, 1.0,
00360
COLOUR_INDEX_8BIT_PIXEL );
00361
00362 ALLOC3D( errors, 2, 3, pixels_rgb->
x_size );
00363
00364 for_less( x, 0, pixels_rgb->
x_size )
00365 {
00366 errors[0][0][x] = 0;
00367 errors[0][1][x] = 0;
00368 errors[0][2][x] = 0;
00369 errors[1][0][x] = 0;
00370 errors[1][1][x] = 0;
00371 errors[1][2][x] = 0;
00372 }
00373
00374 error_row = 0;
00375 dir = 1;
00376
00377 for_less(
y, 0, pixels_rgb->
y_size )
00378 {
00379
if( dir > 0 )
00380 {
00381 first_x = 0;
00382 last_x = pixels_rgb->
x_size;
00383 }
00384
else
00385 {
00386 first_x = pixels_rgb->
x_size-1;
00387 last_x = -1;
00388 }
00389
for( x = first_x; x != last_x; x += dir )
00390 {
00391 col =
PIXEL_RGB_COLOUR(*pixels_rgb,x,
y);
00392 comp[0] = get_Colour_r( col ) + errors[error_row][0][x];
00393 comp[1] = get_Colour_g( col ) + errors[error_row][1][x];
00394 comp[2] = get_Colour_b( col ) + errors[error_row][2][x];
00395
00396 ind =
find_closest_colour( comp[0], comp[1], comp[2],
00397 n_colours, colour_table );
00398
00399 used[0] = get_Colour_r( colour_table[ind] );
00400 used[1] = get_Colour_g( colour_table[ind] );
00401 used[2] = get_Colour_b( colour_table[ind] );
00402
00403 for_less( c, 0, 3 )
00404 {
00405 error = comp[c] - used[c];
00406 seven = ROUND( (Real) error * 7.0/ 16.0 );
00407 five = ROUND( (Real) error * 5.0 / 16.0 );
00408 three = ROUND( (Real) error * 3.0 / 16.0 );
00409 one = error - seven - five - three;
00410
00411
if( x + dir >= 0 && x + dir < pixels_rgb->
x_size )
00412 {
00413 errors[error_row][c][x+dir] += seven;
00414 errors[1-error_row][c][x+dir] += one;
00415 }
00416
00417
if( x - dir >= 0 && x - dir < pixels_rgb->
x_size )
00418 errors[1-error_row][c][x-dir] += three;
00419
00420 errors[1-error_row][c][x] += five;
00421 }
00422
00423
PIXEL_COLOUR_INDEX_8(*pixels_8,x,
y) = (
unsigned char) ind;
00424 }
00425
00426 error_row = 1 - error_row;
00427 dir = - dir;
00428
00429 for_less( x, 0, pixels_rgb->
x_size )
00430 {
00431 errors[1-error_row][0][x] = 0;
00432 errors[1-error_row][1][x] = 0;
00433 errors[1-error_row][2][x] = 0;
00434 }
00435 }
00436
00437 FREE3D( errors );
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 public void resample_pixels(
00457
pixels_struct *pixels,
00458 Transform_2d *transform,
00459
int n_samples,
00460
pixels_struct *new_pixels,
00461 Colour background_colour )
00462 {
00463
int x,
y, i, j;
00464 Real xs, ys, r_sum, g_sum, b_sum;
00465 Real x_trans, y_trans, weight;
00466 Colour colour;
00467 Transform_2d inverse;
00468
00469
if( pixels->
pixel_type !=
RGB_PIXEL ||
00470 new_pixels->
pixel_type !=
RGB_PIXEL )
00471 {
00472 print_error(
"Can only resample 24 bit rgb pixels.\n" );
00473
return;
00474 }
00475
00476 weight = 1.0 / (Real) n_samples / (Real) n_samples;
00477
get_inverse_transform_2d( transform, &inverse );
00478
00479 for_less( x, 0, new_pixels->
x_size )
00480 {
00481 for_less(
y, 0, new_pixels->
y_size )
00482 {
00483
if( n_samples == 1 )
00484 {
00485
transform_point_2d( &inverse, (Real) x, (Real)
y,
00486 &x_trans, &y_trans );
00487
if( x_trans >= -0.5 && x_trans < (Real) pixels->
x_size - 0.5 &&
00488 y_trans >= -0.5 && y_trans < (Real) pixels->
y_size - 0.5 )
00489 {
00490 colour =
PIXEL_RGB_COLOUR(*pixels,ROUND(x_trans),
00491 ROUND(y_trans));
00492 }
00493
else
00494 {
00495 colour = background_colour;
00496 }
00497 }
00498
else
00499 {
00500 r_sum = 0.0;
00501 g_sum = 0.0;
00502 b_sum = 0.0;
00503 for_less( i, 0, n_samples )
00504 {
00505 xs = (Real) x - 0.5 + ((Real) i + 0.5) / (Real) n_samples;
00506
00507 for_less( j, 0, n_samples )
00508 {
00509 ys = (Real)
y - 0.5 + ((Real) j + 0.5) /(Real)n_samples;
00510
transform_point_2d( &inverse, xs, ys,
00511 &x_trans, &y_trans );
00512
if( x_trans >= -0.5 &&
00513 x_trans < (Real) pixels->
x_size - 0.5 &&
00514 y_trans >= -0.5 &&
00515 y_trans < (Real) pixels->
y_size - 0.5 )
00516 {
00517 colour =
PIXEL_RGB_COLOUR(*pixels,ROUND(x_trans),
00518 ROUND(y_trans));
00519 }
00520
else
00521 {
00522 colour = background_colour;
00523 }
00524 r_sum += (Real) get_Colour_r(colour);
00525 g_sum += (Real) get_Colour_g(colour);
00526 b_sum += (Real) get_Colour_b(colour);
00527 }
00528 }
00529
00530 colour = make_Colour( (
int) (r_sum * weight),
00531 (
int) (g_sum * weight),
00532 (
int) (b_sum * weight) );
00533 }
00534
00535
PIXEL_RGB_COLOUR( *new_pixels, x,
y ) = colour;
00536 }
00537 }
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 public void copy_pixel_region(
00558
pixels_struct *pixels,
00559
int x_min,
00560
int x_max,
00561
int y_min,
00562
int y_max,
00563
pixels_struct *new_pixels )
00564 {
00565
int y, y_dest, x_size, y_size;
00566
00567 x_min -= pixels->
x_position;
00568 y_min -= pixels->
y_position;
00569 x_max -= pixels->
x_position;
00570 y_max -= pixels->
y_position;
00571
00572
if( x_min < 0 )
00573 x_min = 0;
00574
if( x_max >= pixels->
x_size )
00575 x_max = pixels->
x_size-1;
00576
00577
if( y_min < 0 )
00578 y_min = 0;
00579
if( y_max >= pixels->
y_size )
00580 y_max = pixels->
y_size-1;
00581
00582 x_size = MAX( 0, x_max - x_min + 1 );
00583 y_size = MAX( 0, y_max - y_min + 1 );
00584
00585
initialize_pixels( new_pixels, pixels->
x_position + x_min,
00586 pixels->
y_position + y_min,
00587 x_size, y_size, pixels->
x_zoom,
00588 pixels->
y_zoom, pixels->
pixel_type );
00589
00590
if( x_size == 0 || y_size == 0 )
00591
return;
00592
00593 for_inclusive(
y, y_min, y_max )
00594 {
00595 y_dest =
y - y_min;
00596
00597
switch( pixels->
pixel_type )
00598 {
00599
case COLOUR_INDEX_8BIT_PIXEL:
00600 (
void) memcpy( (
void *) &
PIXEL_COLOUR_INDEX_8(*new_pixels,0,y_dest),
00601 (
void *) &
PIXEL_COLOUR_INDEX_8(*pixels,x_min,
y),
00602 (size_t) x_size *
00603
sizeof(
PIXEL_COLOUR_INDEX_8(*new_pixels,0,0)) );
00604
break;
00605
00606
case COLOUR_INDEX_16BIT_PIXEL:
00607 (
void) memcpy( (
void *)&
PIXEL_COLOUR_INDEX_16(*new_pixels,0,y_dest),
00608 (
void *) &
PIXEL_COLOUR_INDEX_16(*pixels,x_min,
y),
00609 (size_t) x_size *
00610
sizeof(
PIXEL_COLOUR_INDEX_16(*new_pixels,0,0)) );
00611
break;
00612
00613
case RGB_PIXEL:
00614 (
void) memcpy( (
void *) &
PIXEL_RGB_COLOUR(*new_pixels,0,y_dest),
00615 (
void *) &
PIXEL_RGB_COLOUR(*pixels,x_min,
y),
00616 (size_t) x_size *
00617
sizeof(
PIXEL_RGB_COLOUR(*new_pixels,0,0)) );
00618
break;
00619 }
00620 }
00621 }