00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "vp_global.h"
00032
00033 static void AffineBruteForceRender ANSI_ARGS((vpContext *vpc));
00034 static void ClassifySlice ANSI_ARGS((vpContext *vpc, int slicenum,
00035 float *opc_slice));
00036 static void ShadeSlice ANSI_ARGS((vpContext *vpc, int slicenum,
00037 float *clr_slice));
00038 static void ScaleColors ANSI_ARGS((double scale, float *clr_slice,
00039 int width, int height, int color_channels));
00040 static void AlphaScaleColors ANSI_ARGS((float *opc_slice, float *clr_slice,
00041 int width, int height, int color_channels));
00042 static void DepthCueSlice ANSI_ARGS((vpContext *vpc, float *clr_slice,
00043 int width, int height, int color_channels, double depth_00k,
00044 double depth_di, double depth_dj));
00045 static void TranslateSlice ANSI_ARGS((float *opc_slice, float *clr_slice,
00046 int width, int height, double WgtTL_d, double WgtBL_d, double WgtTR_d,
00047 double WgtBR_d, int color_channels, float *resamp_opc_slice,
00048 float *resmp_clr_slice));
00049 static void CompositeSlice ANSI_ARGS((float *resamp_opc, float *resamp_clr,
00050 int width, int height, int color_channels, void *int_image_ptr,
00051 int int_image_width, double min_opacity));
00052 static void AffineBruteForceWarp ANSI_ARGS((vpContext *vpc));
00053
00054 #define RWCOX
00055 #ifdef RWCOX
00056 static float max_opacity ;
00057 #endif
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 vpResult
00069 vpBruteForceRender(vpc)
00070 vpContext *vpc;
00071 {
00072 int retcode;
00073
00074
00075 if ((retcode = VPCheckRawVolume(vpc)) != VP_OK)
00076 return(retcode);
00077 if ((retcode = VPCheckClassifier(vpc)) != VP_OK)
00078 return(retcode);
00079 if ((retcode = VPCheckShader(vpc)) != VP_OK)
00080 return(retcode);
00081 if ((retcode = VPCheckImage(vpc)) != VP_OK)
00082 return(retcode);
00083 if ((retcode = VPFactorView(vpc)) != VP_OK)
00084 return(retcode);
00085
00086 #ifdef RWCOX
00087 max_opacity = vpc->max_opacity ;
00088 #endif
00089
00090
00091 if (vpc->affine_view)
00092 AffineBruteForceRender(vpc);
00093 else
00094 return(VPSetError(vpc, VPERROR_BAD_OPTION));
00095
00096 return(VP_OK);
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106 static void
00107 AffineBruteForceRender(vpc)
00108 vpContext *vpc;
00109 {
00110 int icount;
00111 int jcount;
00112 int kcount;
00113 int k;
00114 int kstart, kstop;
00115 int kincr;
00116
00117 float slice_u, slice_v;
00118
00119
00120 int slice_u_int;
00121 int slice_v_int;
00122 float slice_u_frac;
00123 float slice_v_frac;
00124 int slice_start_index;
00125 float WgtTL, WgtBL,
00126 WgtTR, WgtBR;
00127
00128
00129 int color_channels;
00130 float *opc_slice;
00131 float *resamp_opc_slice;
00132 float *clr_slice;
00133 float *resamp_clr_slice;
00134 #ifdef FAST_DEPTH_CUEING
00135 float slice_depth_cueing;
00136 float slice_dc_ratio;
00137
00138 #endif
00139 void *intim;
00140
00141 Debug((vpc, VPDEBUG_RENDER, "Algorithm: affine brute force\n"));
00142
00143
00144 switch (vpc->best_view_axis) {
00145 case VP_X_AXIS:
00146 icount = vpc->ylen;
00147 jcount = vpc->zlen;
00148 kcount = vpc->xlen;
00149 break;
00150 case VP_Y_AXIS:
00151 icount = vpc->zlen;
00152 jcount = vpc->xlen;
00153 kcount = vpc->ylen;
00154 break;
00155 case VP_Z_AXIS:
00156 icount = vpc->xlen;
00157 jcount = vpc->ylen;
00158 kcount = vpc->zlen;
00159 break;
00160 default:
00161 VPBug("invalid viewing axis in AffineBruteForceRender");
00162 }
00163
00164
00165 color_channels = vpc->color_channels;
00166 vpc->pad_int_to_maxwidth = 0;
00167 if (color_channels == 1) {
00168 bzero(vpc->int_image.gray_intim, vpc->intermediate_width *
00169 vpc->intermediate_height * sizeof(GrayIntPixel));
00170 } else {
00171 ASSERT(color_channels == 3);
00172 bzero(vpc->int_image.rgb_intim, vpc->intermediate_width *
00173 vpc->intermediate_height * sizeof(RGBIntPixel));
00174 }
00175
00176
00177 Alloc(vpc, opc_slice, float *, icount*jcount*sizeof(float), "opc_slice");
00178 Alloc(vpc, resamp_opc_slice, float *, (icount+1)*(jcount+1)*sizeof(float),
00179 "resamp_opc_slice");
00180 Alloc(vpc, clr_slice, float *, color_channels*icount*jcount*sizeof(float),
00181 "clr_slice");
00182 Alloc(vpc, resamp_clr_slice, float *,
00183 color_channels*(icount+1)*(jcount+1)*sizeof(float),
00184 "resamp_clr_slice");
00185
00186 #ifdef FAST_DEPTH_CUEING
00187
00188 if (vpc->dc_enable) {
00189 slice_dc_ratio = VPSliceDepthCueRatio(vpc);
00190 slice_depth_cueing = 1.;
00191 }
00192 #endif
00193
00194
00195 if (vpc->reverse_slice_order) {
00196 kstart = kcount-1;
00197 kstop = -1;
00198 kincr = -1;
00199 } else {
00200 kstart = 0;
00201 kincr = 1;
00202 kstop = kcount;
00203 }
00204
00205
00206 for (k = kstart; k != kstop; k += kincr) {
00207 ReportStatus(vpc, (double)(k - kstart) / (double)(kstop - kstart));
00208
00209
00210
00211 slice_u = vpc->shear_i * k + vpc->trans_i;
00212 slice_v = vpc->shear_j * k + vpc->trans_j;
00213 slice_u_int = (int)ceil(slice_u) - 1;
00214 slice_v_int = (int)ceil(slice_v) - 1;
00215
00216
00217 slice_u_frac = slice_u - slice_u_int;
00218 slice_v_frac = slice_v - slice_v_int;
00219 WgtTL = slice_u_frac * slice_v_frac;
00220 WgtBL = slice_u_frac * ((float)1. - slice_v_frac);
00221 WgtTR = ((float)1. - slice_u_frac) * slice_v_frac;
00222 WgtBR = ((float)1. - slice_u_frac) * ((float)1. - slice_v_frac);
00223
00224
00225 ClassifySlice(vpc, k, opc_slice);
00226
00227
00228 ShadeSlice(vpc, k, clr_slice);
00229
00230
00231 if (vpc->dc_enable) {
00232 #ifdef FAST_DEPTH_CUEING
00233 ScaleColors(slice_depth_cueing, clr_slice, icount, jcount,
00234 color_channels);
00235 slice_depth_cueing *= slice_dc_ratio;
00236 #else
00237 DepthCueSlice(vpc, clr_slice, icount, jcount, color_channels,
00238 vpc->depth_000 + k*vpc->depth_dk,
00239 vpc->depth_di, vpc->depth_dj);
00240 #endif
00241 }
00242
00243
00244 AlphaScaleColors(opc_slice, clr_slice, icount, jcount, color_channels);
00245
00246
00247 TranslateSlice(opc_slice, clr_slice, icount, jcount,
00248 WgtTL, WgtBL, WgtTR, WgtBR, color_channels,
00249 resamp_opc_slice, resamp_clr_slice);
00250
00251
00252 slice_start_index = slice_u_int + slice_v_int*vpc->intermediate_width;
00253 if (color_channels == 1)
00254 intim = &vpc->int_image.gray_intim[slice_start_index];
00255 else
00256 intim = &vpc->int_image.rgb_intim[slice_start_index];
00257 CompositeSlice(resamp_opc_slice, resamp_clr_slice, icount+1, jcount+1,
00258 color_channels, intim, vpc->intermediate_width,
00259 vpc->min_opacity);
00260 }
00261 ReportStatus(vpc, 1.0);
00262
00263 #ifdef FAST_DEPTH_CUEING
00264
00265 if (vpc->dc_enable)
00266 VPDepthCueIntImage(vpc, vpc->reverse_slice_order ? kcount-1 : 0);
00267 #endif
00268
00269
00270 AffineBruteForceWarp(vpc);
00271
00272
00273 Dealloc(vpc, opc_slice);
00274 Dealloc(vpc, resamp_opc_slice);
00275 Dealloc(vpc, clr_slice);
00276 Dealloc(vpc, resamp_clr_slice);
00277 }
00278
00279
00280
00281
00282
00283
00284
00285 static void
00286 ClassifySlice(vpc, slicenum, opc_slice)
00287 vpContext *vpc;
00288 int slicenum;
00289 float *opc_slice;
00290 {
00291 switch (vpc->best_view_axis) {
00292 case VP_X_AXIS:
00293 VPClassifyBlock(vpc, 1, slicenum, 0, 0, slicenum, vpc->ylen-1,
00294 vpc->zlen-1, opc_slice, 0, sizeof(float),
00295 vpc->ylen*sizeof(float));
00296 break;
00297 case VP_Y_AXIS:
00298 VPClassifyBlock(vpc, 1, 0, slicenum, 0, vpc->xlen-1, slicenum,
00299 vpc->zlen-1, opc_slice, vpc->zlen*sizeof(float),
00300 0, sizeof(float));
00301 break;
00302 case VP_Z_AXIS:
00303 VPClassifyBlock(vpc, 1, 0, 0, slicenum, vpc->xlen-1, vpc->ylen-1,
00304 slicenum, opc_slice, sizeof(float),
00305 vpc->xlen*sizeof(float), 0);
00306 break;
00307 }
00308 }
00309
00310
00311
00312
00313
00314
00315
00316 static void
00317 ShadeSlice(vpc, slicenum, clr_slice)
00318 vpContext *vpc;
00319 int slicenum;
00320 float *clr_slice;
00321 {
00322 int color_bytes;
00323
00324 color_bytes = sizeof(float) * vpc->color_channels;
00325
00326 switch (vpc->best_view_axis) {
00327 case VP_X_AXIS:
00328 VPShadeBlock(vpc, slicenum, 0, 0, slicenum, vpc->ylen-1, vpc->zlen-1,
00329 clr_slice, 0, color_bytes, vpc->ylen*color_bytes);
00330 break;
00331 case VP_Y_AXIS:
00332 VPShadeBlock(vpc, 0, slicenum, 0, vpc->xlen-1, slicenum, vpc->zlen-1,
00333 clr_slice, vpc->zlen*color_bytes, 0, color_bytes);
00334 break;
00335 case VP_Z_AXIS:
00336 VPShadeBlock(vpc, 0, 0, slicenum, vpc->xlen-1, vpc->ylen-1, slicenum,
00337 clr_slice, color_bytes, vpc->xlen*color_bytes, 0);
00338 break;
00339 }
00340 }
00341
00342
00343
00344
00345
00346
00347
00348 static void
00349 ScaleColors(scale, clr_slice, width, height, color_channels)
00350 double scale;
00351 float *clr_slice;
00352 int width;
00353 int height;
00354 int color_channels;
00355 {
00356 int i, j;
00357 float s;
00358
00359 s = scale;
00360
00361 #ifndef RWCOX
00362 for (j = 0; j < height; j++) {
00363 for (i = 0; i < width; i++) {
00364 if (color_channels == 1) {
00365 clr_slice[0] *= s;
00366 } else {
00367 clr_slice[0] *= s;
00368 clr_slice[1] *= s;
00369 clr_slice[2] *= s;
00370 }
00371 clr_slice += color_channels;
00372 }
00373 }
00374 #else
00375 if( color_channels == 1 ){
00376 for (j = 0; j < height; j++) {
00377 for (i = 0; i < width; i++) {
00378 clr_slice[0] *= s;
00379 clr_slice ++;
00380 }
00381 }
00382 } else {
00383 for (j = 0; j < height; j++) {
00384 for (i = 0; i < width; i++) {
00385 clr_slice[0] *= s;
00386 clr_slice[1] *= s;
00387 clr_slice[2] *= s;
00388 clr_slice += 3;
00389 }
00390 }
00391 }
00392 #endif
00393 }
00394
00395
00396
00397
00398
00399
00400
00401 static void
00402 AlphaScaleColors(opc_slice, clr_slice, width, height, color_channels)
00403 float *opc_slice;
00404 float *clr_slice;
00405 int width;
00406 int height;
00407 int color_channels;
00408 {
00409 int i, j;
00410
00411 #ifndef RWCOX
00412 for (j = 0; j < height; j++) {
00413 for (i = 0; i < width; i++) {
00414 if (color_channels == 1) {
00415 clr_slice[0] *= opc_slice[0];
00416 } else {
00417 clr_slice[0] *= opc_slice[0];
00418 clr_slice[1] *= opc_slice[0];
00419 clr_slice[2] *= opc_slice[0];
00420 }
00421 clr_slice += color_channels;
00422 opc_slice++;
00423 }
00424 }
00425 #else
00426 if( color_channels == 1 ){
00427 for (j = 0; j < height; j++) {
00428 for (i = 0; i < width; i++) {
00429 clr_slice[0] *= opc_slice[0];
00430 clr_slice++;
00431 opc_slice++;
00432 }
00433 }
00434 } else {
00435 for (j = 0; j < height; j++) {
00436 for (i = 0; i < width; i++) {
00437 clr_slice[0] *= opc_slice[0];
00438 clr_slice[1] *= opc_slice[0];
00439 clr_slice[2] *= opc_slice[0];
00440 clr_slice += 3;
00441 opc_slice++;
00442 }
00443 }
00444 }
00445 #endif
00446 }
00447
00448
00449
00450
00451
00452
00453
00454 static void
00455 DepthCueSlice(vpc, clr_slice, width, height, color_channels,
00456 depth_00k, depth_di, depth_dj)
00457 vpContext *vpc;
00458 float *clr_slice;
00459 int width;
00460 int height;
00461 int color_channels;
00462 double depth_00k;
00463 double depth_di, depth_dj;
00464
00465 {
00466 int i, j;
00467 double depth, depth_0jk, factor;
00468 double dc_front_factor, dc_density;
00469
00470 dc_front_factor = vpc->dc_front_factor;
00471 dc_density = vpc->dc_density;
00472 depth_0jk = depth_00k;
00473 for (j = 0; j < height; j++) {
00474 depth = depth_0jk;
00475 for (i = 0; i < width; i++) {
00476 if (depth < 0.0)
00477 factor = dc_front_factor * exp(-dc_density);
00478 else
00479 factor = dc_front_factor * exp(-dc_density * (1.0 - depth));
00480 if (color_channels == 1) {
00481 clr_slice[0] *= factor;
00482 } else {
00483 clr_slice[0] *= factor;
00484 clr_slice[1] *= factor;
00485 clr_slice[2] *= factor;
00486 }
00487 clr_slice += color_channels;
00488 depth += depth_di;
00489 }
00490 depth_0jk += depth_dj;
00491 }
00492 }
00493
00494
00495
00496
00497
00498
00499
00500 static void
00501 TranslateSlice(opc_slice, clr_slice, width, height,
00502 WgtTL_d, WgtBL_d, WgtTR_d, WgtBR_d,
00503 color_channels, resamp_opc_slice, resamp_clr_slice)
00504 float *opc_slice;
00505 float *clr_slice;
00506 int width;
00507 int height;
00508 double WgtTL_d;
00509 double WgtBL_d;
00510 double WgtTR_d;
00511 double WgtBR_d;
00512 int color_channels;
00513 float *resamp_opc_slice;
00514
00515 float *resamp_clr_slice;
00516
00517 {
00518 int i, j;
00519 float WgtTL, WgtBL, WgtTR, WgtBR;
00520 float OpcAcc, RClrAcc, GClrAcc, BClrAcc;
00521
00522 WgtTL = WgtTL_d;
00523 WgtBL = WgtBL_d;
00524 WgtTR = WgtTR_d;
00525 WgtBR = WgtBR_d;
00526 for (j = 0; j <= height; j++) {
00527 for (i = 0; i <= width; i++) {
00528 OpcAcc = 0.;
00529 RClrAcc = 0.;
00530 GClrAcc = 0.;
00531 BClrAcc = 0.;
00532 if (i > 0 && j > 0) {
00533 OpcAcc += WgtTL * opc_slice[-1-width];
00534 if (color_channels == 1) {
00535 RClrAcc += WgtTL * clr_slice[-1-width];
00536 } else {
00537 RClrAcc += WgtTL * clr_slice[3*(-1-width)];
00538 GClrAcc += WgtTL * clr_slice[3*(-1-width)+1];
00539 BClrAcc += WgtTL * clr_slice[3*(-1-width)+2];
00540 }
00541 }
00542 if (i > 0 && j < height) {
00543 OpcAcc += WgtBL * opc_slice[-1];
00544 if (color_channels == 1) {
00545 RClrAcc += WgtBL * clr_slice[-1];
00546 } else {
00547 RClrAcc += WgtBL * clr_slice[3*(-1)];
00548 GClrAcc += WgtBL * clr_slice[3*(-1)+1];
00549 BClrAcc += WgtBL * clr_slice[3*(-1)+2];
00550 }
00551 }
00552 if (i < width && j > 0) {
00553 OpcAcc += WgtTR * opc_slice[-width];
00554 if (color_channels == 1) {
00555 RClrAcc += WgtTR * clr_slice[-width];
00556 } else {
00557 RClrAcc += WgtTR * clr_slice[3*(-width)];
00558 GClrAcc += WgtTR * clr_slice[3*(-width)+1];
00559 BClrAcc += WgtTR * clr_slice[3*(-width)+2];
00560 }
00561 }
00562 if (i < width && j < height) {
00563 OpcAcc += WgtBR * opc_slice[0];
00564 if (color_channels == 1) {
00565 RClrAcc += WgtBR * clr_slice[0];
00566 } else {
00567 RClrAcc += WgtBR * clr_slice[3*(0)];
00568 GClrAcc += WgtBR * clr_slice[3*(0)+1];
00569 BClrAcc += WgtBR * clr_slice[3*(0)+2];
00570 }
00571 }
00572 *resamp_opc_slice = OpcAcc;
00573 if (color_channels == 1) {
00574 *resamp_clr_slice = RClrAcc;
00575 } else {
00576 resamp_clr_slice[0] = RClrAcc;
00577 resamp_clr_slice[1] = GClrAcc;
00578 resamp_clr_slice[2] = BClrAcc;
00579 }
00580 resamp_opc_slice++;
00581 resamp_clr_slice += color_channels;
00582 if (i != width) {
00583 opc_slice++;
00584 clr_slice += color_channels;;
00585 }
00586 }
00587 }
00588 }
00589
00590
00591
00592
00593
00594
00595
00596 static void
00597 CompositeSlice(resamp_opc, resamp_clr, width, height, color_channels,
00598 int_image_ptr, int_image_width, min_opacity)
00599 float *resamp_opc;
00600 float *resamp_clr;
00601 int width;
00602 int height;
00603 int color_channels;
00604 void *int_image_ptr;
00605
00606 int int_image_width;
00607 double min_opacity;
00608 {
00609 int i, j;
00610 float old_opc, old_r, old_g, old_b;
00611 float new_opc, new_r, new_g, new_b;
00612 GrayIntPixel *gray_intim;
00613 RGBIntPixel *rgb_intim;
00614
00615 if (color_channels == 1)
00616 gray_intim = int_image_ptr;
00617 else
00618 rgb_intim = int_image_ptr;
00619 for (j = 0; j < height; j++) {
00620 for (i = 0; i < width; i++) {
00621 if (*resamp_opc > min_opacity) {
00622 if (color_channels == 1) {
00623 old_opc = gray_intim->opcflt;
00624 #ifdef RWCOX
00625 if( old_opc < max_opacity ){
00626 #endif
00627 old_r = gray_intim->clrflt;
00628 new_opc = old_opc + *resamp_opc * ((float)1. - old_opc);
00629 new_r = old_r + *resamp_clr * ((float)1. - old_opc);
00630 gray_intim->opcflt = new_opc;
00631 gray_intim->clrflt = new_r;
00632 #ifdef RWCOX
00633 }
00634 #endif
00635 } else {
00636 old_opc = rgb_intim->opcflt;
00637 #ifdef RWCOX
00638 if( old_opc < max_opacity ){
00639 #endif
00640 old_r = rgb_intim->rclrflt;
00641 old_g = rgb_intim->gclrflt;
00642 old_b = rgb_intim->bclrflt;
00643 new_opc = old_opc + *resamp_opc * ((float)1. - old_opc);
00644 new_r = old_r + resamp_clr[0] * ((float)1. - old_opc);
00645 new_g = old_g + resamp_clr[1] * ((float)1. - old_opc);
00646 new_b = old_b + resamp_clr[2] * ((float)1. - old_opc);
00647 rgb_intim->opcflt = new_opc;
00648 rgb_intim->rclrflt = new_r;
00649 rgb_intim->gclrflt = new_g;
00650 rgb_intim->bclrflt = new_b;
00651 #ifdef RWCOX
00652 }
00653 #endif
00654 }
00655
00656 }
00657 resamp_opc++;
00658 if (color_channels == 1) {
00659 resamp_clr++;
00660 gray_intim++;
00661 } else {
00662 resamp_clr += 3;
00663 rgb_intim++;
00664 }
00665 }
00666 if (color_channels == 1)
00667 gray_intim += int_image_width - width;
00668 else
00669 rgb_intim += int_image_width - width;
00670 }
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680 static void
00681 AffineBruteForceWarp(vpc)
00682 vpContext *vpc;
00683 {
00684 unsigned char *int_image;
00685
00686 int int_width;
00687 int int_height;
00688 int int_scanbytes;
00689 unsigned char *image;
00690 int i, j;
00691 float int_i_flt, int_j_flt;
00692
00693 float int_i_int, int_j_int;
00694 int int_i, int_j;
00695 double alpha_i, alpha_j;
00696 double wgt;
00697 GrayIntPixel *gray_pix;
00698 RGBIntPixel *rgb_pix;
00699 double denom;
00700 double ma, mb, mc, md, me, mf;
00701 float r, g, b, alpha;
00702 int r_int, g_int, b_int, alpha_int;
00703 int color_channels;
00704 int pixel_type;
00705
00706
00707 color_channels = vpc->color_channels;
00708 pixel_type = vpc->pixel_type;
00709 int_width = vpc->intermediate_width;
00710 int_height = vpc->intermediate_height;
00711 if (vpc->color_channels == 1) {
00712 int_image = (unsigned char *)vpc->int_image.gray_intim;
00713 if (vpc->pad_int_to_maxwidth)
00714 int_scanbytes = vpc->max_intermediate_width*sizeof(GrayIntPixel);
00715 else
00716 int_scanbytes = vpc->intermediate_width*sizeof(GrayIntPixel);
00717 } else {
00718 int_image = (unsigned char *)vpc->int_image.rgb_intim;
00719 if (vpc->pad_int_to_maxwidth)
00720 int_scanbytes = vpc->max_intermediate_width*sizeof(RGBIntPixel);
00721 else
00722 int_scanbytes = vpc->intermediate_width*sizeof(RGBIntPixel);
00723 }
00724
00725
00726
00727 denom = 1. / (vpc->warp_2d[0][0]*vpc->warp_2d[1][1] -
00728 vpc->warp_2d[0][1]*vpc->warp_2d[1][0]);
00729 ma = vpc->warp_2d[1][1] * denom;
00730 mb = -vpc->warp_2d[0][1] * denom;
00731 mc = (vpc->warp_2d[0][1]*vpc->warp_2d[1][2] -
00732 vpc->warp_2d[1][1]*vpc->warp_2d[0][2]) * denom;
00733 md = -vpc->warp_2d[1][0] * denom;
00734 me = vpc->warp_2d[0][0] * denom;
00735 mf = (vpc->warp_2d[1][0]*vpc->warp_2d[0][2] -
00736 vpc->warp_2d[0][0]*vpc->warp_2d[1][2]) * denom;
00737
00738
00739 for (j = 0; j < vpc->image_height; j++) {
00740 image = (unsigned char *)vpc->image + j*vpc->image_bytes_per_scan;
00741 for (i = 0; i < vpc->image_width; i++) {
00742
00743 int_i_flt = ma*i + mb*j + mc;
00744 int_j_flt = md*i + me*j + mf;
00745
00746
00747 int_i_int = floor(int_i_flt);
00748 int_j_int = floor(int_j_flt);
00749 alpha_i = int_i_flt - int_i_int;
00750 alpha_j = int_j_flt - int_j_int;
00751 int_i = (int)int_i_int;
00752 int_j = (int)int_j_int;
00753
00754
00755 r = 0;
00756 g = 0;
00757 b = 0;
00758 alpha = 0;
00759 if (int_i >= 0 && int_i < int_width &&
00760 int_j >= 0 && int_j < int_height) {
00761 wgt = (1. - alpha_i) * (1. - alpha_j);
00762 if (color_channels == 1) {
00763 gray_pix = (GrayIntPixel *)(int_image + int_j*
00764 int_scanbytes) + int_i;
00765 r += gray_pix->clrflt*wgt;
00766 alpha += gray_pix->opcflt*wgt;
00767 } else {
00768 rgb_pix = (RGBIntPixel *)(int_image + int_j*
00769 int_scanbytes) + int_i;
00770 r += rgb_pix->rclrflt*wgt;
00771 g += rgb_pix->gclrflt*wgt;
00772 b += rgb_pix->bclrflt*wgt;
00773 alpha += rgb_pix->opcflt*wgt;
00774 }
00775 }
00776 if (int_i >= 0 && int_i < int_width &&
00777 int_j >= -1 && int_j < int_height-1) {
00778 wgt = (1. - alpha_i) * alpha_j;
00779 if (color_channels == 1) {
00780 gray_pix = (GrayIntPixel *)(int_image + (int_j+1)*
00781 int_scanbytes) + int_i;
00782 r += gray_pix->clrflt*wgt;
00783 alpha += gray_pix->opcflt*wgt;
00784 } else {
00785 rgb_pix = (RGBIntPixel *)(int_image + (int_j+1)*
00786 int_scanbytes) + int_i;
00787 r += rgb_pix->rclrflt*wgt;
00788 g += rgb_pix->gclrflt*wgt;
00789 b += rgb_pix->bclrflt*wgt;
00790 alpha += rgb_pix->opcflt*wgt;
00791 }
00792 }
00793 if (int_i >= -1 && int_i < int_width-1 &&
00794 int_j >= 0 && int_j < int_height) {
00795 wgt = alpha_i * (1. - alpha_j);
00796 if (color_channels == 1) {
00797 gray_pix = (GrayIntPixel *)(int_image + int_j*
00798 int_scanbytes) + int_i+1;
00799 r += gray_pix->clrflt*wgt;
00800 alpha += gray_pix->opcflt*wgt;
00801 } else {
00802 rgb_pix = (RGBIntPixel *)(int_image + int_j*
00803 int_scanbytes) + int_i+1;
00804 r += rgb_pix->rclrflt*wgt;
00805 g += rgb_pix->gclrflt*wgt;
00806 b += rgb_pix->bclrflt*wgt;
00807 alpha += rgb_pix->opcflt*wgt;
00808 }
00809 }
00810 if (int_i >= -1 && int_i < int_width-1 &&
00811 int_j >= -1 && int_j < int_height-1) {
00812 wgt = alpha_i * alpha_j;
00813 if (color_channels == 1) {
00814 gray_pix = (GrayIntPixel *)(int_image + (int_j+1)*
00815 int_scanbytes) + int_i+1;
00816 r += gray_pix->clrflt*wgt;
00817 alpha += gray_pix->opcflt*wgt;
00818 } else {
00819 rgb_pix = (RGBIntPixel *)(int_image + (int_j+1)*
00820 int_scanbytes) + int_i+1;
00821 r += rgb_pix->rclrflt*wgt;
00822 g += rgb_pix->gclrflt*wgt;
00823 b += rgb_pix->bclrflt*wgt;
00824 alpha += rgb_pix->opcflt*wgt;
00825 }
00826 }
00827
00828
00829 if (alpha > 255.)
00830 alpha_int = 255;
00831 else if (alpha < 0.)
00832 alpha_int = 0;
00833 else
00834 alpha_int = alpha;
00835 if (r > 255.)
00836 r_int = 255;
00837 else if (r < 0)
00838 r_int = 0;
00839 else
00840 r_int = r;
00841
00842 if (color_channels == 3) {
00843 if (g > 255.)
00844 g_int = 255;
00845 else if (g < 0.)
00846 g_int = 0;
00847 else
00848 g_int = g;
00849 if (b > 255.)
00850 b_int = 255;
00851 else if (b < 0.)
00852 b_int = 0;
00853 else
00854 b_int = b;
00855 }
00856
00857
00858 switch (pixel_type) {
00859 case VP_ALPHA:
00860 *image++ = alpha_int;
00861 break;
00862 case VP_LUMINANCE:
00863 *image++ = r_int;
00864 break;
00865 case VP_LUMINANCEA:
00866 *image++ = r_int;
00867 *image++ = alpha_int;
00868 break;
00869 case VP_RGB:
00870 *image++ = r_int;
00871 *image++ = g_int;
00872 *image++ = b_int;
00873 break;
00874 case VP_RGBA:
00875 *image++ = r_int;
00876 *image++ = g_int;
00877 *image++ = b_int;
00878 *image++ = alpha_int;
00879 break;
00880 case VP_BGR:
00881 *image++ = b_int;
00882 *image++ = g_int;
00883 *image++ = r_int;
00884 break;
00885 case VP_ABGR:
00886 *image++ = alpha_int;
00887 *image++ = b_int;
00888 *image++ = g_int;
00889 *image++ = r_int;
00890 break;
00891 default:
00892 VPBug("bad pixel type");
00893 }
00894 }
00895 }
00896 }
00897
00898 #ifdef DEBUG
00899 StoreFloatImage(data, width, height, scale, filename)
00900 float *data;
00901 int width, height;
00902 double scale;
00903 char *filename;
00904 {
00905 unsigned char *image, *imptr;
00906 int i, j;
00907
00908 image = (unsigned char *)malloc(width*height);
00909 imptr = image;
00910 for (j = 0; j < height; j++) {
00911 for (i = 0; i < width; i++) {
00912 *imptr++ = (int)rint(scale * *data++);
00913 }
00914 }
00915 VprWriteGrayscaleTIFF(filename, width, height, width, image);
00916 free(image);
00917 }
00918 #endif