1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
package com.android.rs.refocus;
import android.support.v8.renderscript.RenderScript;
import android.support.v8.renderscript.Allocation;
import android.support.v8.renderscript.Element;
import com.android.rs.refocus.renderscript.ScriptField_KernelInfo;
/**
* A class that manages the blur kernel matrices of a blending layer that
* interface between Java and Render Script. This class will be specialized for
* float in f32 package and for byte in u8 package.
*
* @author zhl@google.com (Li Zhang)
*/
public class KernelDataForRenderScript {
/**
* A flag to turn on using optimized RenderScript.
* False means using original version; true means using the new version.
*/
private static boolean UseNewRS = false;
/**
* Number of sub-pixels that is used to generate anti-aliased blur kernel
* matrix. That is, we divide one pixel into
* {@code NUM_SUB_PIXELS * NUM_SUB_PIXELS} sub-pixels to test whether or not a
* pixel is in the blur disk.
*/
protected static final int NUM_SUB_PIXELS = 5;
/**
* The width of the pixels that are used to pad the image boundary to avoid
* boundary checking in filtering operation.
*/
private static final int MAX_KERNEL_RADIUS =
computeKernelRadiusFromDiskRadius(BlurStack.getMaxDiskRadius());
/**
* The length of an array that concatenates all (vectorized) kernel matrices.
*/
protected int stackLength;
/**
* A class automatically generated by Render Script compiler, which contains
* required auxiliary information to parse {@code kernelStack}, including the
* starting position of each kernel matrix in a memory buffer and the radius
* (radius_x,radius_y) of each kernel matrix. The names radius_x and radius_y
* follow C++ style because render script is C language.
*/
protected ScriptField_KernelInfo kernelInfo;
/** Java array version of the current kernel info. Used when UseNewRS is true.
* 4*m: offset; 4*m + 1: radius_x; 4*m + 2: radius_y
*/
protected float[] infoArray;
/** An allocation used to store global allocation of stack info. Used when UseNewRS is true.
*
*/
public Allocation infoAllocation;
public static int getNumSubPixels() {
return NUM_SUB_PIXELS;
}
public static int getMaxKernelRadius() {
return MAX_KERNEL_RADIUS;
}
public static void setUseNewRS(boolean choice) {UseNewRS = choice;}
/**
* Computes the kernel matrix radius from the blur disk radius.
*
* @param diskRadius blur disk radius
* @return kernel matrix radius
*/
public static int computeKernelRadiusFromDiskRadius(float diskRadius) {
return (int) (diskRadius) + 1;
}
public ScriptField_KernelInfo getKernelInfo() {
return kernelInfo;
}
/**
* Initializes {@code kernelInfo}.
*
* @param targetLayer the index of a target layer
* @param blurStack an instance of {@code BlurStack}
* @param renderScript an instance of {@code RenderScript}
*/
protected KernelDataForRenderScript(int targetLayer, BlurStack blurStack,
RenderScript renderScript) {
if (UseNewRS) {
// Use the new version of renderscript files.
int numDepths = blurStack.getNumDepths(targetLayer);
infoAllocation = Allocation.createSized(
renderScript, Element.F32_4(renderScript),
numDepths);
infoArray = new float[4*numDepths];
// Generates information for each blur kernel matrix.
int offset = 0;
for (int m = 0; m < numDepths; ++m) {
int depth = blurStack.getDepth(targetLayer, m);
float diskRadius = blurStack.getDiskRadius(depth);
int kernelRadius = computeKernelRadiusFromDiskRadius(diskRadius);
infoArray[m*4] = offset;
infoArray[m*4 + 1] = kernelRadius;
infoArray[m*4 + 2] = kernelRadius;
// Updates offset variable.
int kernelLength = (2 * kernelRadius + 1) * (2 * kernelRadius + 1);
offset += kernelLength;
}
infoAllocation.copyFrom(infoArray);
stackLength = offset;
} else {
// Use original version of renderscript files.
int numDepths = blurStack.getNumDepths(targetLayer);
kernelInfo = new ScriptField_KernelInfo(renderScript, numDepths);
// Generates information for each blur kernel matrix.
int offset = 0;
for (int m = 0; m < numDepths; ++m) {
int depth = blurStack.getDepth(targetLayer, m);
float diskRadius = blurStack.getDiskRadius(depth);
int kernelRadius = computeKernelRadiusFromDiskRadius(diskRadius);
// Sets information for the {@code m}'th kernel matrix.
kernelInfo.set_offset(m, offset, true);
kernelInfo.set_radius_x(m, kernelRadius, true);
kernelInfo.set_radius_y(m, kernelRadius, true);
// Updates offset variable.
int kernelLength = (2 * kernelRadius + 1) * (2 * kernelRadius + 1);
offset += kernelLength;
}
stackLength = offset;
}
}
}
|