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    Log.d(myTAG, "PackOutputImage: "+(endnow - startnow)+ " ns" );
67
68    buffers.outAllocation.copyTo(buffers.outputImage);
69    return buffers.outputImage;
70  }
71
72  /*
73   * Utility Method to extract intermediatory result
74   */
75  private  void extractSharpImage(String name) {
76
77    Bitmap mBitmap = Bitmap.createBitmap(buffers.inputImage.getWidth(),
78            buffers.inputImage.getHeight(), Bitmap.Config.ARGB_8888);
79    Allocation mAllocation = Allocation.createFromBitmap(renderScript, mBitmap);
80    scriptC.forEach_PackSharpImage(mAllocation);
81
82    mAllocation.copyTo(mBitmap);
83    MediaStoreSaver.savePNG(mBitmap, "sharpF32", name, renderScript.getApplicationContext());
84  }
85  /*
86   * Utility Method to extract intermediatory result
87   */
88  private  void extractFuzzyImage(String name) {
89
90    Bitmap mBitmap = Bitmap.createBitmap(buffers.inputImage.getWidth(),
91            buffers.inputImage.getHeight(), Bitmap.Config.ARGB_8888);
92    Allocation mAllocation = Allocation.createFromBitmap(renderScript, mBitmap);
93    scriptC.forEach_PackFuzzyImage(mAllocation);
94
95    mAllocation.copyTo(mBitmap);
96    MediaStoreSaver.savePNG(mBitmap, "fuzzyF32", name, renderScript.getApplicationContext());
97  }
98
99  @Override
100  protected void setTargetLayer(LayerInfo layerInfo) {
101    scriptC.invoke_SetTargetLayer(layerInfo.frontDepth, layerInfo.backDepth);
102  }
103
104  @Override
105  protected void setBlendInfo(int dilationRadius) {
106    scriptC.invoke_SetBlendInfo(dilationRadius);
107  }
108
109  @Override
110  protected void setKernelData(int targetLayer, BlurStack blurStack) {
111    KernelDataForRenderScriptF32 kernelData =
112        new KernelDataForRenderScriptF32(targetLayer, blurStack, renderScript);
113
114    if (ENABLE_FAST_FILTER
115        && kernelData.minDiskRadius > MIN_DISC_RADIUS_FOR_FAST_FILTER) {
116      useFastFilterForCurrentLayer = true;
117    } else {
118      useFastFilterForCurrentLayer = false;
119    }
120
121    scriptC.bind_g_kernel_info(kernelData.getKernelInfo());
122    scriptC.bind_g_kernel_stack(kernelData.stackAllocation);
123  }
124
125  @Override
126  protected void computeLayerMatteBehindFocalDepth() {
127    // Marks active pixels (pixels that are on this target layer);
128    // Marks adjacent pixels that are close enough to active pixels;
129    long startnow;
130    long endnow;
131    startnow = System.nanoTime();
132    scriptC.forEach_MarkLayerMask(buffers.inAllocation);
133    endnow = System.nanoTime();
134    Log.d(myTAG, "MarkLayerMask: "+(endnow - startnow)+ " ns" );
135
136    startnow = System.nanoTime();
137    scriptC.forEach_ComputeLayerMatteBehindFocalDepth(buffers.inAllocation);
138    endnow = System.nanoTime();
139    Log.d(myTAG, "ComputeLayerMatteBehindFocalDepth: "+(endnow - startnow)+ " ns" );
140  }
141
142  @Override
143  protected void filterLayerBehindFocalDepth() {
144    // Filters the target layer and saves the result to {@code g_accum_map} in
145    // .rs file.
146    long startnow;
147    long endnow;
148    if (useFastFilterForCurrentLayer) {
149      scriptC.invoke_SetUseIntegralImage(1);
150      Script.LaunchOptions launchOptions = new Script.LaunchOptions();
151      launchOptions.setX(0, 1);
152      launchOptions.setY(0, buffers.inputImage.getHeight());
153
154      startnow = System.nanoTime();
155      scriptC.forEach_ComputeIntegralImageForLayerBehindFocalDepth(
156          buffers.inAllocation, launchOptions);
157      endnow = System.nanoTime();
158      Log.d(myTAG, "ComputeIntegralImageForLayerBehindFocalDepth: "+(endnow - startnow)+ " ns" );
159    } else {
160      scriptC.invoke_SetUseIntegralImage(0);
161    }
162
163    startnow = System.nanoTime();
164    scriptC.forEach_FilterLayerBehindFocalDepth(buffers.inAllocation);
165    endnow = System.nanoTime();
166    Log.d(myTAG, "FilterLayerBehindFocalDepth: "+(endnow - startnow)+ " ns" );
167
168    //extractFuzzyImage("fuzzy_behind");
169    //extractSharpImage("sharp_behind");
170  }
171
172  @Override
173  protected void updateSharpImageUsingFuzzyImage() {
174		// Log the kernel execution time
175    long startnow;
176    long endnow;
177    startnow = System.nanoTime();
178    scriptC.forEach_UpdateSharpImageUsingFuzzyImage(buffers.inAllocation);
179    endnow = System.nanoTime();
180    Log.d(myTAG, "UpdateSharpImageUsingFuzzyImage: "+(endnow - startnow)+ " ns" );
181
182    //extractSharpImage("sharp_update");
183  }
184
185  @Override
186  protected void computeLayerMatteInFrontOfFocalDepth() {
187    // Marks active pixels (pixels that are on this target layer);
188    // Marks adjacent pixels that are close enough to active pixels;
189    long startnow;
190    long endnow;
191    startnow = System.nanoTime();
192    scriptC.forEach_MarkLayerMask(buffers.inAllocation);
193    endnow = System.nanoTime();
194    Log.d(myTAG, "MarkLayerMask: "+(endnow - startnow)+ " ns" );
195
196    startnow = System.nanoTime();
197    scriptC.forEach_ComputeLayerMatteInFrontOfFocalDepth(buffers.inAllocation);
198    endnow = System.nanoTime();
199    Log.d(myTAG, "ComputeLayerMatteInFrontOfFocalDepth: "+(endnow - startnow)+ " ns" );
200  }
201
202  @Override
203  protected void filterLayerInFrontOfFocalDepth() {
204    // Filters the target layer and accumulates the result to {@code
205    // g_accum_map} in .rs file.
206    long startnow;
207    long endnow;
208    if (useFastFilterForCurrentLayer) {
209      scriptC.invoke_SetUseIntegralImage(1);
210      Script.LaunchOptions launchOptions = new Script.LaunchOptions();
211      launchOptions.setX(0, 1);
212      launchOptions.setY(0, buffers.inputImage.getHeight());
213
214      startnow = System.nanoTime();
215      scriptC.forEach_ComputeIntegralImageForLayerInFrontOfFocalDepth(
216          buffers.inAllocation, launchOptions);
217      endnow = System.nanoTime();
218      Log.d(myTAG, "ComputeIntegralImageForLayerInFrontOfFocalDepth: "+(endnow - startnow)+ " ns" );
219    } else {
220      scriptC.invoke_SetUseIntegralImage(0);
221    }
222    startnow = System.nanoTime();
223    scriptC.forEach_FilterLayerInFrontOfFocalDepth(buffers.inAllocation);
224    endnow = System.nanoTime();
225    Log.d(myTAG, "FilterLayerInFrontOfFocalDepth: "+(endnow - startnow)+ " ns" );
226
227    //extractFuzzyImage("fuzzy_front");
228    //extractSharpImage("sharp_front");
229  }
230
231  @Override
232  protected void finalizeFuzzyImageUsingSharpImage() {
233    // Blends {@code g_accum_map} and {@code g_focus_map} in .rs file.
234    // Saves the result in {@code g_accum_map}.
235    long startnow;
236    long endnow;
237    startnow = System.nanoTime();
238    scriptC.forEach_FinalizeFuzzyImageUsingSharpImage(buffers.inAllocation);
239    endnow = System.nanoTime();
240    Log.d(myTAG, "FinalizeFuzzyImageUsingSharpImage: "+(endnow - startnow)+ " ns" );
241  }
242}
243