1package com.android.rs.refocus.f32;
2
3
4import com.android.rs.refocus.BlurStack;
5import com.android.rs.refocus.KernelDataForRenderScript;
6import com.android.rs.refocus.LayerInfo;
7import com.android.rs.refocus.MediaStoreSaver;
8import com.android.rs.refocus.R;
9import com.android.rs.refocus.RefocusFilter;
10import com.android.rs.refocus.renderscript.ScriptC_layered_filter_fast_f32;
11
12import android.graphics.Bitmap;
13import android.support.v8.renderscript.Allocation;
14import android.support.v8.renderscript.RenderScript;
15import android.support.v8.renderscript.Script;
16import android.util.Log;
17/**
18 * An accelerated implementation of RefocusFilter using float32 as pixel
19 * representation. The corresponding RenderScript class is
20 * ScriptC_layered_filter_f32. Integral image is used for the speedup.
21 *
22 * Example Usage:
23 *
24 * {@code RenderScript renderScript = RenderScript.create(context);}
25 * {@code RefocusFilterF32 rfFilter = new RefocusFilterF32(renderScript);}
26 * {@code ProgressCallback progress;}
27 * {@code Bitmap result = rfFilter.compute(rgbdImage, blurStack, progress);}
28 *
29 * @author zhl@google.com (Li Zhang)
30 */
31public class RefocusFilterF32 extends
32    RefocusFilter<ScriptC_layered_filter_fast_f32> {
33  private static final String myTAG = "RefocusFilterF32";
34  private static final boolean ENABLE_FAST_FILTER = true;
35  private static final float MIN_DISC_RADIUS_FOR_FAST_FILTER = 3;
36  boolean useFastFilterForCurrentLayer = false;
37  ImageBuffersForRenderScriptF32 buffers;
38
39  public RefocusFilterF32(RenderScript rs) {
40    super(rs);
41  }
42
43  @Override
44  protected void initializeScriptAndBuffers(Bitmap inputImage,
45      LayerInfo focalLayer) {
46    scriptC = new ScriptC_layered_filter_fast_f32(renderScript);
47
48    // Allocates, binds, and initializes buffers that interface between Java
49    // and Render Script.
50    // + 1 is for the boundary case of using integral image.
51    KernelDataForRenderScript.setUseNewRS(false);
52    int margin = KernelDataForRenderScript.getMaxKernelRadius() + 1;
53    buffers = new ImageBuffersForRenderScriptF32(inputImage, margin,
54        renderScript, scriptC);
55    buffers.initializeRenderScript(focalLayer, scriptC);
56  }
57
58  @Override
59  protected Bitmap extractResultImage() {
60    // Extracts the result from .rs file to {@code buffers.outputImage} in Java.
61    long startnow;
62    long endnow;
63    startnow = System.nanoTime();
64    scriptC.forEach_PackOutputImage(buffers.outAllocation);
65    endnow = System.nanoTime();
66    logTiming(myTAG, "PackOutputImage", endnow - startnow);
67
68    startnow = System.nanoTime();
69    buffers.outAllocation.copyTo(buffers.outputImage);
70    endnow = System.nanoTime();
71    logTiming(myTAG, "CopyOutputImage", endnow - startnow);
72
73    return buffers.outputImage;
74  }
75
76  /*
77   * Utility Method to extract intermediatory result
78   */
79  private  void extractSharpImage(String name) {
80
81    Bitmap mBitmap = Bitmap.createBitmap(buffers.inputImage.getWidth(),
82            buffers.inputImage.getHeight(), Bitmap.Config.ARGB_8888);
83    Allocation mAllocation = Allocation.createFromBitmap(renderScript, mBitmap);
84    scriptC.forEach_PackSharpImage(mAllocation);
85
86    mAllocation.copyTo(mBitmap);
87    MediaStoreSaver.savePNG(mBitmap, "sharpF32", name, renderScript.getApplicationContext());
88  }
89  /*
90   * Utility Method to extract intermediatory result
91   */
92  private  void extractFuzzyImage(String name) {
93
94    Bitmap mBitmap = Bitmap.createBitmap(buffers.inputImage.getWidth(),
95            buffers.inputImage.getHeight(), Bitmap.Config.ARGB_8888);
96    Allocation mAllocation = Allocation.createFromBitmap(renderScript, mBitmap);
97    scriptC.forEach_PackFuzzyImage(mAllocation);
98
99    mAllocation.copyTo(mBitmap);
100    MediaStoreSaver.savePNG(mBitmap, "fuzzyF32", name, renderScript.getApplicationContext());
101  }
102
103  @Override
104  protected void setTargetLayer(LayerInfo layerInfo) {
105    scriptC.invoke_SetTargetLayer(layerInfo.frontDepth, layerInfo.backDepth);
106  }
107
108  @Override
109  protected void setBlendInfo(int dilationRadius) {
110    scriptC.invoke_SetBlendInfo(dilationRadius);
111  }
112
113  @Override
114  protected void setKernelData(int targetLayer, BlurStack blurStack) {
115    KernelDataForRenderScriptF32 kernelData =
116        new KernelDataForRenderScriptF32(targetLayer, blurStack, renderScript);
117
118    if (ENABLE_FAST_FILTER
119        && kernelData.minDiskRadius > MIN_DISC_RADIUS_FOR_FAST_FILTER) {
120      useFastFilterForCurrentLayer = true;
121    } else {
122      useFastFilterForCurrentLayer = false;
123    }
124
125    scriptC.bind_g_kernel_info(kernelData.getKernelInfo());
126    scriptC.bind_g_kernel_stack(kernelData.stackAllocation);
127  }
128
129  @Override
130  protected void computeLayerMatteBehindFocalDepth() {
131    // Marks active pixels (pixels that are on this target layer);
132    // Marks adjacent pixels that are close enough to active pixels;
133    long startnow;
134    long endnow;
135    startnow = System.nanoTime();
136    scriptC.forEach_MarkLayerMask(buffers.inAllocation);
137    endnow = System.nanoTime();
138    logTiming(myTAG, "MarkLayerMask", endnow - startnow);
139
140    startnow = System.nanoTime();
141    scriptC.forEach_ComputeLayerMatteBehindFocalDepth(buffers.inAllocation);
142    endnow = System.nanoTime();
143    logTiming(myTAG, "ComputeLayerMatteBehindFocalDepth", endnow - startnow);
144  }
145
146  @Override
147  protected void filterLayerBehindFocalDepth() {
148    // Filters the target layer and saves the result to {@code g_accum_map} in
149    // .rs file.
150    long startnow;
151    long endnow;
152    if (useFastFilterForCurrentLayer) {
153      scriptC.invoke_SetUseIntegralImage(1);
154      Script.LaunchOptions launchOptions = new Script.LaunchOptions();
155      launchOptions.setX(0, 1);
156      launchOptions.setY(0, buffers.inputImage.getHeight());
157
158      startnow = System.nanoTime();
159      scriptC.forEach_ComputeIntegralImageForLayerBehindFocalDepth(
160          buffers.inAllocation, launchOptions);
161      endnow = System.nanoTime();
162      logTiming(myTAG, "ComputeIntegralImageForLayerBehindFocalDepth", endnow - startnow);
163    } else {
164      scriptC.invoke_SetUseIntegralImage(0);
165    }
166
167    startnow = System.nanoTime();
168    scriptC.forEach_FilterLayerBehindFocalDepth(buffers.inAllocation);
169    endnow = System.nanoTime();
170    logTiming(myTAG, "FilterLayerBehindFocalDepth", endnow - startnow);
171
172    //extractFuzzyImage("fuzzy_behind");
173    //extractSharpImage("sharp_behind");
174  }
175
176  @Override
177  protected void updateSharpImageUsingFuzzyImage() {
178		// Log the kernel execution time
179    long startnow;
180    long endnow;
181    startnow = System.nanoTime();
182    scriptC.forEach_UpdateSharpImageUsingFuzzyImage(buffers.inAllocation);
183    endnow = System.nanoTime();
184    logTiming(myTAG, "UpdateSharpImageUsingFuzzyImage", endnow - startnow);
185
186    //extractSharpImage("sharp_update");
187  }
188
189  @Override
190  protected void computeLayerMatteInFrontOfFocalDepth() {
191    // Marks active pixels (pixels that are on this target layer);
192    // Marks adjacent pixels that are close enough to active pixels;
193    long startnow;
194    long endnow;
195    startnow = System.nanoTime();
196    scriptC.forEach_MarkLayerMask(buffers.inAllocation);
197    endnow = System.nanoTime();
198    logTiming(myTAG, "MarkLayerMask", endnow - startnow);
199
200    startnow = System.nanoTime();
201    scriptC.forEach_ComputeLayerMatteInFrontOfFocalDepth(buffers.inAllocation);
202    endnow = System.nanoTime();
203    logTiming(myTAG, "ComputeLayerMatteInFrontOfFocalDepth", endnow - startnow);
204  }
205
206  @Override
207  protected void filterLayerInFrontOfFocalDepth() {
208    // Filters the target layer and accumulates the result to {@code
209    // g_accum_map} in .rs file.
210    long startnow;
211    long endnow;
212    if (useFastFilterForCurrentLayer) {
213      scriptC.invoke_SetUseIntegralImage(1);
214      Script.LaunchOptions launchOptions = new Script.LaunchOptions();
215      launchOptions.setX(0, 1);
216      launchOptions.setY(0, buffers.inputImage.getHeight());
217
218      startnow = System.nanoTime();
219      scriptC.forEach_ComputeIntegralImageForLayerInFrontOfFocalDepth(
220          buffers.inAllocation, launchOptions);
221      endnow = System.nanoTime();
222      logTiming(myTAG, "ComputeIntegralImageForLayerInFrontOfFocalDepth", endnow - startnow);
223    } else {
224      scriptC.invoke_SetUseIntegralImage(0);
225    }
226    startnow = System.nanoTime();
227    scriptC.forEach_FilterLayerInFrontOfFocalDepth(buffers.inAllocation);
228    endnow = System.nanoTime();
229    logTiming(myTAG, "FilterLayerInFrontOfFocalDepth", endnow - startnow);
230
231    //extractFuzzyImage("fuzzy_front");
232    //extractSharpImage("sharp_front");
233  }
234
235  @Override
236  protected void finalizeFuzzyImageUsingSharpImage() {
237    // Blends {@code g_accum_map} and {@code g_focus_map} in .rs file.
238    // Saves the result in {@code g_accum_map}.
239    long startnow;
240    long endnow;
241    startnow = System.nanoTime();
242    scriptC.forEach_FinalizeFuzzyImageUsingSharpImage(buffers.inAllocation);
243    endnow = System.nanoTime();
244    logTiming(myTAG, "FinalizeFuzzyImageUsingSharpImage", endnow - startnow);
245  }
246}
247