Home | History | Annotate | Download | only in refocus
      1 #pragma version(1)
      2 #pragma rs java_package_name(android.renderscript.cts.refocus)
      3 
      4 // This is a speedup version of layered_filter_f32.rs using summation table.
      5 // Several kernel functions and global functions for refocus rendering using
      6 // Render Script. These functions are accessible from Java side. The assumptions
      7 // made in this file are (consistent with Java side):
      8 //
      9 // 1. The depth value varies between 1 and number of depth levels. 0 is reserved
     10 // for invalid pixels, e.g., padded pixels around image boundary.
     11 // 2. The depth value represents inverse depth. Larger depths are closer to the
     12 // camera.
     13 // 3. The depth values are grouped into several blending layers.
     14 // 4. The focal layer (i.e., the global variable g_focal_layer) is the depth
     15 // value interval that has no blur.
     16 //
     17 // For the following kernel functions defined in this rs file, the input
     18 // arguments have the following meaning:
     19 //
     20 // @param in an input RGBD pixel with @in.a being quantized inverse depth.
     21 // @param x x-coordinate of @param in in the unpadded input image.
     22 // @param y y-coordinate of @param in in the unpadded input image.
     23 
     24 #include "image_and_kernel.rsh"
     25 #include "camera_response.rsh"
     26 #include "layer_info.rsh"
     27 #include "pixel_format_f32.rsh"
     28 #include "luts_for_speedup_f32.rsh"
     29 #include "layered_filter_f32_helper.rsh"
     30 
     31 // Image size of padded images: g_sharp_image and g_fuzzy_image.
     32 static ImageSize_t g_image_size;
     33 
     34 static CameraResponse_t g_camera_response;
     35 
     36 float4 *g_sharp_image_buffer = NULL;
     37 float4 *g_fuzzy_image_buffer = NULL;
     38 float4 *g_integral_image_buffer = NULL;
     39 
     40 // This image buffer is used to store input image initially.
     41 // Then the input image gets updated as each layer is processed from the
     42 // back-most to the focal depth. This image buffer is padded.
     43 static SharpPixelF32_t *g_sharp_image = NULL;
     44 
     45 // This image buffer is used to save an integral image of g_sharp_image
     46 // modulated by the visibility mask.
     47 static float4 *g_integral_image = NULL;
     48 
     49 // whether or not to use integral image in this iteration.
     50 static int g_use_integral_image;
     51 
     52 // This image buffer is used to store output image, both for intermediate
     53 // results and final result.
     54 // In the first pass from back-most to focal depth, g_fuzzy_image holds the
     55 // layer filtering result temporarily and then the result is used to update the
     56 // input image after each layer is processed.
     57 // In the second pass from front-most to focal depth, g_fuzzy_image accumulates
     58 // all the layer filtering results and in the end, the accumulation result is
     59 // blended with the input image (which has been updated in the first pass) to
     60 // generate the final result. This image buffer is padded.
     61 static FuzzyPixelF32_t *g_fuzzy_image = NULL;
     62 
     63 // The info of current layer that is being processed.
     64 static LayerInfo_t g_target_layer;
     65 // The dilation radius that controls how the current layer should be blended
     66 // with previous layers.
     67 static BlendInfo_t g_blend_info;
     68 
     69 // The depth level that is in focus.
     70 static LayerInfo_t g_focal_layer;
     71 
     72 // For depth d, let n = d-g_target_layer.back_depth be the relative depth index.
     73 // g_kernel_stack+g_kernel_info[n].offset is the pointer to the kernel matrix
     74 // for this depth level.
     75 // The kernel has a center at
     76 // (g_kernel_info[n].radius_x, g_kernel_info[n].radius_y).
     77 // And the kernel has a size of
     78 // (2*center_x+1, 2*center_y+1) ;
     79 float *g_kernel_stack;
     80 KernelInfo_t *g_kernel_info;
     81 
     82 // Precomputed LUTs for speedup.
     83 static VisibilityProbability_t g_visibility_probability;
     84 static SecantOffset_t g_secant_offset;
     85 
     86 static const float g_kOneOver255 = 1.0f / 255.0f;
     87 static const float g_kAlmostOne = .998f;
     88 
     89 // (1 << g_kDepthScaleShift) must be the same as BlurStack::DEPTH_SCALE.
     90 static const int g_kDepthScaleShift = 2;
     91 // g_kMaxDepth must be the same as BlurStack::MAX_DETPH.
     92 static const int g_kMaxDepth = 256 >> g_kDepthScaleShift;
     93 
     94 // Copies an input (unpadded) RGBD image into g_sharp_image, which has been
     95 // padded with margin. Initialize other fields.
     96 void __attribute__((kernel))
     97 UnpackInputImage(uchar4 in, uint32_t x, uint32_t y) {
     98   // Maps (x,y) to the padded image coordinate system.
     99   x += g_image_size.margin;
    100   y += g_image_size.margin;
    101 
    102   const int index = y * g_image_size.width + x;
    103 
    104   SharpPixelF32_t *sharp = g_sharp_image + index;
    105   sharp->red = in.r * g_kOneOver255;
    106   sharp->green = in.g * g_kOneOver255;
    107   sharp->blue = in.b * g_kOneOver255;
    108 
    109   sharp->red =
    110       ApplyLUT_Float(sharp->red, g_camera_response.lut_remove_crf_float);
    111   sharp->green =
    112       ApplyLUT_Float(sharp->green, g_camera_response.lut_remove_crf_float);
    113   sharp->blue =
    114       ApplyLUT_Float(sharp->blue, g_camera_response.lut_remove_crf_float);
    115 
    116   sharp->actual_depth = g_kMaxDepth - (in.a >> g_kDepthScaleShift);
    117 
    118   sharp->active = 0;
    119 
    120   sharp->matte = 0;
    121 
    122   sharp->dilated_depth = 0;
    123 }
    124 
    125 // Marks active pixels that are on the target layer.
    126 // Initializes the matte of active pixels to be the dilation_radius+1, which is
    127 // equivalent to 1.
    128 // Initializes dilated_depth of active pixels and pixels that are close to
    129 // active pixels to be actual depths.
    130 void __attribute__((kernel)) MarkLayerMask(uchar4 in, uint32_t x, uint32_t y) {
    131   const int actual_depth = g_kMaxDepth - (in.a >> g_kDepthScaleShift);
    132   if (!OnTheLayer(actual_depth, &g_target_layer)) return;
    133 
    134   // Maps (x,y) to the padded image coordinate system.
    135   x += g_image_size.margin;
    136   y += g_image_size.margin;
    137 
    138   const int index = y * g_image_size.width + x;  // index of this pixel
    139   SharpPixelF32_t *sharp = g_sharp_image + index;
    140 
    141   // Marks this pixel as active.
    142   sharp->active = 1;
    143   sharp->matte = g_blend_info.dilation_radius + 1;
    144   sharp->dilated_depth = sharp->actual_depth;
    145 
    146   // Next, tries to figure out whether or not this pixel is on the boundary
    147   // between active and inactive pixels
    148   int is_this_pixel_on_boundary = 0;
    149   SharpPixelF32_t *sharp_nbr = NULL;
    150 
    151   // Top
    152   sharp_nbr = sharp - g_image_size.width;
    153   is_this_pixel_on_boundary |=
    154       ValidDepthNotOnTheLayer(sharp_nbr->actual_depth, &g_target_layer);
    155 
    156   // Bottom
    157   sharp_nbr = sharp + g_image_size.width;
    158   is_this_pixel_on_boundary |=
    159       ValidDepthNotOnTheLayer(sharp_nbr->actual_depth, &g_target_layer);
    160 
    161   // Left
    162   sharp_nbr = sharp - 1;
    163   is_this_pixel_on_boundary |=
    164       ValidDepthNotOnTheLayer(sharp_nbr->actual_depth, &g_target_layer);
    165 
    166   // Right
    167   sharp_nbr = sharp + 1;
    168   is_this_pixel_on_boundary |=
    169       ValidDepthNotOnTheLayer(sharp_nbr->actual_depth, &g_target_layer);
    170 
    171   if (!is_this_pixel_on_boundary) {
    172     return;
    173   }
    174 
    175   // Marks pixels near the boundary of active pixels to compute matte later.
    176   const int kernel_center_x = g_blend_info.dilation_radius;
    177   const int kernel_center_y = g_blend_info.dilation_radius;
    178   const int kernel_dim_x = 2 * kernel_center_x + 1;
    179 
    180   // Moves sharp_nbr to the top left corner of this pixel.
    181   sharp_nbr = sharp - (kernel_center_y * g_image_size.width + kernel_center_x);
    182 
    183   // Visits every pixel in the window of radius (center_x,center_y)
    184   // surrounding this pixel.
    185   const int jump_to_next_pixel = 1;
    186   const int jump_to_next_row = g_image_size.width - kernel_dim_x;
    187   for (int j = -kernel_center_y; j <= kernel_center_y; ++j) {
    188     for (int i = -kernel_center_x; i <= kernel_center_x; ++i) {
    189       // Initializes dilated_depth as actual_depth.
    190       // The dilated_depth will then be updated in distance transform later.
    191       // A valid, non-zero dilated_depth indicates distance transform is
    192       // needed for the pixel. Otherwise, the distance transform will be
    193       // skipped.
    194       sharp_nbr->dilated_depth = sharp_nbr->actual_depth;
    195 
    196       sharp_nbr += jump_to_next_pixel;
    197     }
    198     sharp_nbr += jump_to_next_row;
    199   }
    200 }
    201 
    202 // Distance transform in processing layers in pass one from the back-most to
    203 // the sharp depth.
    204 void __attribute__((kernel))
    205 ComputeLayerMatteBehindFocalDepth(uchar4 in, uint32_t x, uint32_t y) {
    206   // Maps (x,y) to the padded image coordinate system.
    207   x += g_image_size.margin;
    208   y += g_image_size.margin;
    209 
    210   const int index = y * g_image_size.width + x;
    211   SharpPixelF32_t *sharp = g_sharp_image + index;
    212 
    213   if (sharp->active == 0 && sharp->dilated_depth) {
    214     // This pixel is not active but within the dilation radius of the active
    215     // pixels.
    216     if (NotInFrontOfTheLayer(sharp->actual_depth, &g_target_layer)) {
    217       // We do not need to compute matte for depths in front of this layer,
    218       // because these pixels will be over-written later and hence we don't need
    219       // to blend them now.
    220       ComputeLayerMatteHelper(sharp, x, y, &g_image_size,
    221                               g_blend_info.dilation_radius);
    222     }
    223   }
    224 }
    225 
    226 // Distance transform in processing layers in pass two from the front-most to
    227 // the sharp depth.
    228 void __attribute__((kernel))
    229 ComputeLayerMatteInFrontOfFocalDepth(uchar4 in, uint32_t x, uint32_t y) {
    230   // Maps (x,y) to the padded image coordinate system.
    231   x += g_image_size.margin;
    232   y += g_image_size.margin;
    233 
    234   const int index = y * g_image_size.width + x;
    235   SharpPixelF32_t *sharp = g_sharp_image + index;
    236 
    237   if (sharp->active == 0 && sharp->dilated_depth) {
    238     // This pixel is not active but within the dilation radius of the active
    239     // pixels.
    240     FuzzyPixelF32_t *fuzzy = g_fuzzy_image + index;
    241     if (fuzzy->alpha < g_kAlmostOne) {
    242       // This pixel has not been completely covered by layers in front of the
    243       // current layer.
    244       ComputeLayerMatteHelper(sharp, x, y, &g_image_size,
    245                               g_blend_info.dilation_radius);
    246     }
    247   }
    248 }
    249 
    250 // Computes integral image for target layer in processing layers in pass one
    251 // from the back-most to the sharp depth.
    252 void __attribute__((kernel))
    253 ComputeIntegralImageForLayerBehindFocalDepth(uchar4 in, uint32_t x,
    254                                              uint32_t y) {
    255   // Maps (x,y) to the padded image coordinate system.
    256   // Kernel invocation should make sure x = 0.
    257   y += g_image_size.margin;
    258 
    259   // Gets the visibility probability lookup table for the target layer depth.
    260   const float *vis_prob =
    261       g_visibility_probability.lut[g_target_layer.front_depth];
    262 
    263   const int index = y * g_image_size.width;
    264   const SharpPixelF32_t *sharp = g_sharp_image + index;
    265   const SharpPixelF32_t *last_sharp = sharp + g_image_size.width;
    266   float4 *integral = g_integral_image + index;
    267   float4 prev_integral_value = 0;
    268   for (; sharp != last_sharp; sharp++, integral++) {
    269     const float weight = vis_prob[sharp->actual_depth];
    270     float4 this_value = {weight * sharp->red, weight * sharp->green,
    271                          weight * sharp->blue, weight};
    272     *integral = prev_integral_value + this_value;
    273     prev_integral_value = *integral;
    274   }
    275 }
    276 
    277 void __attribute__((kernel))
    278 ComputeIntegralImageForLayerInFrontOfFocalDepth(uchar4 in, uint32_t x,
    279                                                 uint32_t y) {
    280   // Maps (x,y) to the padded image coordinate system.
    281   // Kernel invocation should make sure x = 0.
    282   y += g_image_size.margin;
    283 
    284   const int index = y * g_image_size.width;
    285   const SharpPixelF32_t *sharp = g_sharp_image + index;
    286   const SharpPixelF32_t *last_sharp = sharp + g_image_size.width;
    287   float4 *integral = g_integral_image + index;
    288   float4 prev_integral_value = 0;
    289   for (; sharp != last_sharp; sharp++, integral++) {
    290     const float weight = ValidDepth(sharp->actual_depth);
    291     float4 this_value = {weight * sharp->red, weight * sharp->green,
    292                          weight * sharp->blue, weight};
    293     *integral = prev_integral_value + this_value;
    294     prev_integral_value = *integral;
    295   }
    296 }
    297 
    298 // Filters target layer in processing layers in pass one from the back-most to
    299 // the sharp depth.
    300 void __attribute__((kernel))
    301 FilterLayerBehindFocalDepth(uchar4 in, uint32_t x, uint32_t y) {
    302   // Maps (x,y) to the padded image coordinate system.
    303   x += g_image_size.margin;
    304   y += g_image_size.margin;
    305 
    306   const int index = y * g_image_size.width + x;
    307   SharpPixelF32_t *sharp = g_sharp_image + index;
    308 
    309   if (sharp->matte == 0) {
    310     return;
    311   }
    312 
    313   // At this point, sharp->dilated_depth must be within the depth range of
    314   // this target layer. Hence, the kernel_info below is a valid pointer.
    315   const KernelInfo_t *kernel_info =
    316       g_kernel_info + sharp->dilated_depth - g_target_layer.back_depth;
    317 
    318   // Saves the filtering result in g_fuzzy_image temporarily.
    319   if (g_use_integral_image) {
    320     g_fuzzy_image[index] = FilterLayerUsingRowwiseIntegralImage(
    321         x, y, &g_image_size, kernel_info, g_integral_image, &g_secant_offset);
    322   } else {
    323     g_fuzzy_image[index] = FilterLayerBehindFocalDepthHelper(
    324         x, y, &g_image_size, &g_target_layer, kernel_info, g_kernel_stack,
    325         g_sharp_image, &g_visibility_probability);
    326   }
    327   // Once the kernel invoke is completed, uses the g_fuzzy_image to update
    328   // g_sharp_image.
    329 }
    330 
    331 // Filters target layer in processing layers in pass two from the front-most
    332 // to the focus depth.
    333 void __attribute__((kernel))
    334 FilterLayerInFrontOfFocalDepth(uchar4 in, uint32_t x, uint32_t y) {
    335   // Maps (x,y) to the padded image coordinate system.
    336   x += g_image_size.margin;
    337   y += g_image_size.margin;
    338 
    339   const int index = y * g_image_size.width + x;
    340   SharpPixelF32_t *sharp = g_sharp_image + index;
    341 
    342   const int depth = sharp->dilated_depth;
    343   if (depth == 0) {
    344     return;
    345   }
    346 
    347   // At this point, this pixel must be either active or close enough to an
    348   // active pixel.
    349   // For such a pixel, its matte value can still be zero if its distance
    350   // transform to the active pixels is larger than dilation_radius.
    351   int matte = sharp->matte;
    352 
    353   // Resets fields of this pixel to prepare for the next iteration.
    354   sharp->active = 0;
    355   sharp->dilated_depth = 0;
    356   sharp->matte = 0;
    357   // Does not reset sharp->actual_depth, which will be used in future
    358   // iterations.
    359 
    360   if (matte == 0) {
    361     return;
    362   }
    363 
    364   // At this point, sharp->dilated_depth must be within the depth range of
    365   // this target layer. Hence kernel_info below is a valid pointer.
    366   const KernelInfo_t *kernel_info =
    367       g_kernel_info + depth - g_target_layer.back_depth;
    368 
    369   FuzzyPixelF32_t result;
    370   if (g_use_integral_image) {
    371     result = FilterLayerUsingRowwiseIntegralImage(
    372         x, y, &g_image_size, kernel_info, g_integral_image, &g_secant_offset);
    373   } else {
    374     result = FilterLayerInFrontOfFocalDepthHelper(
    375         x, y, &g_image_size, kernel_info, g_kernel_stack, g_sharp_image);
    376   }
    377 
    378   FuzzyPixelF32_t *fuzzy = g_fuzzy_image + index;
    379   // Because matte !=0 here, fuzzy->a < g_kAlmostOne must be true.
    380   // Otherwise, ComputeLayerMatteHelper won't be called in
    381   // ComputeLayerMatteInFrontOfFocalDepth, which results in a zero matte.
    382 
    383   // Accumulates the filtering result to fuzzy.
    384   const float capacity = 1.0f - fuzzy->alpha;
    385   const float factor = capacity * (float)matte * g_blend_info.matte_normalizer;
    386   fuzzy->red += factor * result.red;
    387   fuzzy->green += factor * result.green;
    388   fuzzy->blue += factor * result.blue;
    389   fuzzy->alpha += factor;
    390 }
    391 
    392 // Replaces active pixels in g_sharp_image with the filtering result saved in
    393 // g_fuzzy_image. Does the replacement in a soft way by blending g_sharp_image
    394 // and g_fuzzy_image using the matte field.
    395 void __attribute__((kernel))
    396 UpdateSharpImageUsingFuzzyImage(uchar4 in, uint32_t x, uint32_t y) {
    397   // Maps (x,y) to the padded image coordinate system.
    398   x += g_image_size.margin;
    399   y += g_image_size.margin;
    400 
    401   const int index = y * g_image_size.width + x;
    402   SharpPixelF32_t *sharp = g_sharp_image + index;
    403 
    404   const int depth = sharp->dilated_depth;
    405 
    406   if (depth == 0) {
    407     return;
    408   }
    409 
    410   // At this point, this pixel must be either active or close enough to an
    411   // active pixel.
    412   // For such a pixel, its matte value can still be zero if its distance
    413   // transform to the active pixels is larger than dilation_radius.
    414   const int matte = sharp->matte;
    415 
    416   // Resets fields of this pixel to prepare for future layer processing (pass
    417   // two).
    418   sharp->active = 0;
    419   sharp->dilated_depth = 0;
    420   sharp->matte = 0;
    421   // Does not reset sharp->actual depth, which will be used in future
    422   // layer processing.
    423 
    424   if (matte == 0) {
    425     return;
    426   }
    427 
    428   FuzzyPixelF32_t *fuzzy = g_fuzzy_image + index;
    429   float factor = (float)matte * g_blend_info.matte_normalizer;
    430   // The following blending amounts to:
    431   // sharp = (1 - factor) * sharp + factor * fuzzy.
    432   sharp->red += factor * (fuzzy->red - sharp->red);
    433   sharp->green += factor * (fuzzy->green - sharp->green);
    434   sharp->blue += factor * (fuzzy->blue - sharp->blue);
    435 
    436   fuzzy->red = 0;
    437   fuzzy->green = 0;
    438   fuzzy->blue = 0;
    439   fuzzy->alpha = 0;
    440 }
    441 
    442 // Fills in the pixels on or behind the focal depth in g_fuzzy_image using
    443 // pixels in g_sharp_image. Does the filling in a soft way by blending using the
    444 // matte field.
    445 void __attribute__((kernel))
    446 FinalizeFuzzyImageUsingSharpImage(uchar4 in, uint32_t x, uint32_t y) {
    447   // Maps (x,y) to the padded image coordinate system.
    448   x += g_image_size.margin;
    449   y += g_image_size.margin;
    450 
    451   const int index = y * g_image_size.width + x;
    452   const SharpPixelF32_t *sharp = g_sharp_image + index;
    453   FuzzyPixelF32_t *fuzzy = g_fuzzy_image + index;
    454 
    455   // Tests whether this pixel has a valid depth behind the focal depth.
    456   if (sharp->actual_depth && sharp->actual_depth <= g_focal_layer.front_depth) {
    457     // The alpha channel for sharp is 1.
    458     // fuzzy is a result of accumulation and hence is pre-multiplied with alpha.
    459     // The following blending amounts to:
    460     // fuzzy = fuzzy + (1 - fuzzy->a) * sharp.
    461     float capacity = 1.0f - fuzzy->alpha;
    462     fuzzy->red += sharp->red * capacity;
    463     fuzzy->green += sharp->green * capacity;
    464     fuzzy->blue += sharp->blue * capacity;
    465     fuzzy->alpha = 1.0f;
    466   }
    467 }
    468 
    469 // Copies g_fuzzy_image to output color image, excluding the padded margin.
    470 // (x, y) is the pixel coordinate in the output image.
    471 uchar4 __attribute__((kernel)) PackOutputImage(uint32_t x, uint32_t y) {
    472   // Maps (x,y) to the padded image coordinate system.
    473   x += g_image_size.margin;
    474   y += g_image_size.margin;
    475 
    476   // Returns the pixel at (x,y) after applying CRF.
    477   const int index = y * g_image_size.width + x;
    478   const FuzzyPixelF32_t *fuzzy = g_fuzzy_image + index;
    479 
    480   // Applies Camera Response using LUT.
    481   float4 result;
    482   result.r = ApplyLUT_Float(fuzzy->red, g_camera_response.lut_apply_crf_float);
    483   result.g =
    484       ApplyLUT_Float(fuzzy->green, g_camera_response.lut_apply_crf_float);
    485   result.b = ApplyLUT_Float(fuzzy->blue, g_camera_response.lut_apply_crf_float);
    486   result.a = fuzzy->alpha;
    487 
    488   return rsPackColorTo8888(result);
    489 }
    490 
    491 // Copies g_fuzzy_image to output color image, excluding the padded margin.
    492 // (x, y) is the pixel coordinate in the output image.
    493 uchar4 __attribute__((kernel)) PackSharpImage(uint32_t x, uint32_t y) {
    494   // Maps (x,y) to the padded image coordinate system.
    495   x += g_image_size.margin;
    496   y += g_image_size.margin;
    497 
    498   // Returns the pixel at (x,y) after applying CRF.
    499   const int index = y * g_image_size.width + x;
    500   const SharpPixelF32_t *sharp = g_sharp_image + index;
    501 
    502   // Applies Camera Response using LUT.
    503   float4 result;
    504   result.r = ApplyLUT_Float(sharp->red, g_camera_response.lut_apply_crf_float);
    505   result.g =
    506       ApplyLUT_Float(sharp->green, g_camera_response.lut_apply_crf_float);
    507   result.b = ApplyLUT_Float(sharp->blue, g_camera_response.lut_apply_crf_float);
    508 
    509   return rsPackColorTo8888(result);
    510 }
    511 
    512 // Copies g_fuzzy_image to output color image, excluding the padded margin.
    513 // (x, y) is the pixel coordinate in the output image.
    514 uchar4 __attribute__((kernel)) PackFuzzyImage(uint32_t x, uint32_t y) {
    515   // Maps (x,y) to the padded image coordinate system.
    516   x += g_image_size.margin;
    517   y += g_image_size.margin;
    518 
    519   // Returns the pixel at (x,y) after applying CRF.
    520   const int index = y * g_image_size.width + x;
    521   const FuzzyPixelF32_t *fuzzy = g_fuzzy_image + index;
    522 
    523   // Applies Camera Response using LUT.
    524   float4 result;
    525   result.r = ApplyLUT_Float(fuzzy->red, g_camera_response.lut_apply_crf_float);
    526   result.g =
    527       ApplyLUT_Float(fuzzy->green, g_camera_response.lut_apply_crf_float);
    528   result.b = ApplyLUT_Float(fuzzy->blue, g_camera_response.lut_apply_crf_float);
    529   result.a = fuzzy->alpha;
    530 
    531   return rsPackColorTo8888(result);
    532 }
    533 
    534 void SetTargetLayer(int front, int back) {
    535   g_target_layer.front_depth = front;
    536   g_target_layer.back_depth = back;
    537 }
    538 
    539 void SetBlendInfo(int radius) {
    540   g_blend_info.dilation_radius = radius;
    541   g_blend_info.matte_normalizer = 1.0f / (radius + 1);
    542 }
    543 
    544 void SetUseIntegralImage(int use_integral_image) {
    545   g_use_integral_image = use_integral_image;
    546 }
    547 
    548 void InitializeF32(int width, int height, int margin, int front, int back) {
    549   SetImageSize(width, height, margin, &g_image_size);
    550   g_focal_layer.front_depth = front;
    551   g_focal_layer.back_depth = back;
    552 
    553   g_sharp_image = (SharpPixelF32_t *)g_sharp_image_buffer;
    554   g_integral_image = g_integral_image_buffer;
    555   g_fuzzy_image = (FuzzyPixelF32_t *)g_fuzzy_image_buffer;
    556 
    557   const int num_pixels = width * height;
    558   ResetSharpImage(g_sharp_image, num_pixels);
    559   ResetIntegralImage(g_integral_image, num_pixels);
    560   ResetFuzzyImage(g_fuzzy_image, num_pixels);
    561 
    562   InitializeRadiusOffset(&g_secant_offset);
    563   InitializeVisibilityProbability(&g_visibility_probability, front, back);
    564   InitializeDefaultCameraResponse(&g_camera_response);
    565 }
    566