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