1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.renderscript.cts.refocus.f32; 18 19 import android.renderscript.Allocation; 20 import android.renderscript.Element; 21 import android.renderscript.RenderScript; 22 import android.renderscript.cts.refocus.BlurStack; 23 import android.renderscript.cts.refocus.KernelDataForRenderScript; 24 25 import java.util.Arrays; 26 27 /** 28 * A class that manages the blur kernel matrices of a blending layer that 29 * interface between Java and Render Script. 30 */ 31 public class KernelDataForRenderScriptF32 extends KernelDataForRenderScript { 32 /** 33 * A stack of blur kernel matrices packed into a continuous memory buffer. 34 */ 35 float[] kernelStack; 36 37 /** 38 * The minimum blur disk in the stack. 39 */ 40 float minDiskRadius; 41 42 /** 43 * An RenderScript Allocation for kernelStack. 44 */ 45 Allocation stackAllocation; 46 47 /** 48 * Initializes {@code kernelStack} and {@code kernelInfo}. 49 * 50 * @param targetLayer the index of a target layer 51 * @param blurStack an instance of {@code BlurStack} 52 * @param renderScript an instance of {@code RenderScript} 53 */ KernelDataForRenderScriptF32(int targetLayer, BlurStack blurStack, RenderScript renderScript)54 public KernelDataForRenderScriptF32(int targetLayer, BlurStack blurStack, 55 RenderScript renderScript) { 56 super(targetLayer, blurStack, renderScript); 57 // stackLength is set in super. 58 59 kernelStack = new float[stackLength]; 60 int numDepths = blurStack.getNumDepths(targetLayer); 61 minDiskRadius = BlurStack.getMaxDiskRadius(); 62 for (int m = 0; m < numDepths; ++m) { 63 int depth = blurStack.getDepth(targetLayer, m); 64 float diskRadius = blurStack.getDiskRadius(depth); 65 float[] kernelMatrix = getKernel(diskRadius); 66 System.arraycopy(kernelMatrix, 0, kernelStack, kernelInfo.get_offset(m), 67 kernelMatrix.length); 68 minDiskRadius = Math.min(minDiskRadius, diskRadius); 69 } 70 71 stackAllocation = Allocation.createSized(renderScript, 72 Element.F32(renderScript), kernelStack.length); 73 stackAllocation.copyFrom(kernelStack); 74 } 75 76 /** 77 * Returns the kernel matrix of a depth level. 78 * 79 * @param diskRadius disk radius of the kernel. 80 * @return the kernel matrix of the disk radius. 81 */ getKernel(float diskRadius)82 public float[] getKernel(float diskRadius) { 83 int kernelRadius = computeKernelRadiusFromDiskRadius(diskRadius); 84 return generateDiskKernelArray(diskRadius, kernelRadius); 85 } 86 87 /** 88 * Generates a blur kernel matrix for a blur disk with radius 89 * {@code diskRadius}. 90 * 91 * @param diskRadius radius of blur disk 92 * @param kernelRadius radius of blur kernel matrix 93 * @return a kernel matrix represented as an array 94 */ generateDiskKernelArray(float diskRadius, int kernelRadius)95 private static float[] generateDiskKernelArray(float diskRadius, 96 int kernelRadius) { 97 int kernelDim = 2 * kernelRadius + 1; 98 int kernelLength = kernelDim * kernelDim; 99 100 float[] kernel = new float[kernelLength]; 101 Arrays.fill(kernel, 0); 102 103 // Generates {@code NUM_SUB_PIXELS*NUM_SUB_PIXELS} sub-pixel shifts {@code 104 // (dx,dy)} uniformly within [-0.5,0.5]*[-0.5,0.5]. 105 // For each shift, tests whether or not the shifted pixel is within the 106 // disc and accumulates the count. 107 float diskRadius2 = diskRadius * diskRadius; 108 float dy0 = -0.5f + 1.0f / (2 * getNumSubPixels()); 109 float dx0 = -0.5f + 1.0f / (2 * getNumSubPixels()); 110 111 float sumKernelValues = 0; 112 for (int v = 0; v < getNumSubPixels(); ++v) { 113 float dy = dy0 + (float) v / (float) getNumSubPixels(); 114 for (int u = 0; u < getNumSubPixels(); ++u) { 115 float dx = dx0 + (float) u / (float) getNumSubPixels(); 116 for (int y = 0; y < kernelDim; ++y) { 117 float yf = y - kernelRadius + dy; 118 for (int x = 0; x < kernelDim; ++x) { 119 float xf = x - kernelRadius + dx; 120 if (yf * yf + xf * xf <= diskRadius2) { 121 kernel[y * kernelDim + x] += 1; 122 sumKernelValues += 1; 123 } 124 } 125 } 126 } 127 } 128 129 // Normalizes kernel elements such that they sum up to 1. 130 for (int n = 0; n < kernelLength; ++n) { 131 kernel[n] /= sumKernelValues; 132 } 133 134 return kernel; 135 } 136 } 137