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