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 com.android.rs.refocus; 18 19 import android.content.Context; 20 import android.graphics.Bitmap; 21 import android.graphics.BitmapFactory; 22 import android.net.Uri; 23 import com.android.rs.refocus.image.RangeInverseDepthTransform; 24 import com.android.rs.refocus.image.RangeLinearDepthTransform; 25 import java.io.FileNotFoundException; 26 import java.io.IOException; 27 import java.io.InputStream; 28 29 public class DepthImage { 30 private final String mFormat; 31 private final double mFar; 32 private final double mNear; 33 private final Bitmap mDepthBitmap; 34 private final double mBlurAtInfinity; 35 private final double mFocalDistance; 36 private final double mDepthOfField; 37 private final double mFocalPointX; 38 private final double mFocalPointY; 39 private final DepthTransform mDepthTransform; 40 DepthImage(String format, double far, double near, Bitmap depthBitmap, double blurAtInfinity, double focalDistance, double depthOfField, double focalPointX, double focalPointY, DepthTransform depthTransform)41 public DepthImage(String format, double far, double near, 42 Bitmap depthBitmap, double blurAtInfinity, 43 double focalDistance, double depthOfField, 44 double focalPointX, double focalPointY, 45 DepthTransform depthTransform) { 46 mFormat = format; 47 mFar = far; 48 mNear = near; 49 mDepthBitmap = depthBitmap; 50 mBlurAtInfinity = blurAtInfinity; 51 mFocalDistance = focalDistance; 52 mDepthOfField = depthOfField; 53 mFocalPointX = focalPointX; 54 mFocalPointY = focalPointY; 55 mDepthTransform = depthTransform; 56 } 57 createFromXMPMetadata(Context context, Uri image)58 public static DepthImage createFromXMPMetadata(Context context, Uri image) 59 throws IOException { 60 InputStream input = context.getContentResolver().openInputStream(image); 61 XmpDepthDecode decode = new XmpDepthDecode(input); 62 return new DepthImage(decode.getFormat(), decode.getFar(), 63 decode.getNear(), decode.getDepthBitmap(), 64 decode.getBlurAtInfinity(), 65 decode.getFocalDistance(), 66 decode.getDepthOfField(), 67 decode.getFocalPointX(), 68 decode.getFocalPointY(), 69 decode.getDepthTransform()); 70 } 71 createFromDepthmap(Context context, Uri uriDepthmap)72 public static DepthImage createFromDepthmap(Context context, Uri uriDepthmap) 73 throws IOException { 74 Bitmap bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uriDepthmap)); 75 if (bitmap == null) { 76 throw new FileNotFoundException(uriDepthmap.toString()); 77 } 78 79 double near = 12.0; 80 double far = 120.0; 81 DepthTransform transform = new RangeInverseDepthTransform((float)near, (float)far); 82 return new DepthImage(RangeInverseDepthTransform.FORMAT, 83 far, 84 near, 85 bitmap, // depthmap 86 5.0, // blur at ininity 87 15.0, // focal distance 88 0.1, // depth of field 89 0.5, // x of focal point 90 0.5, // y of focla point 91 transform); 92 } 93 94 private static class MinMax { 95 public float min; 96 public float max; 97 MinMax(float min, float max)98 public MinMax(float min, float max) { 99 this.min = min; 100 this.max = max; 101 } 102 create(float min, float max)103 public static MinMax create(float min, float max) { 104 return new MinMax(min, max); 105 } 106 } 107 findMinAndMax(final float[] array)108 private static MinMax findMinAndMax(final float[] array) { 109 float min = array[0]; 110 float max = min; 111 for (int i = 1; i < array.length; i++) { 112 final float x = array[i]; 113 if (x < min) { 114 min = x; 115 } else if (x > max) { 116 max = x; 117 } 118 } 119 return MinMax.create(min, max); 120 } 121 createFromPFM(Context context, Uri uriPFM)122 public static DepthImage createFromPFM(Context context, Uri uriPFM) 123 throws IOException { 124 PortableFloatMap pfm = new PortableFloatMap(context.getContentResolver().openInputStream(uriPFM)); 125 126 final float[] floatPixels = pfm.getPixelArray(); 127 int[] intPixels = new int[floatPixels.length]; 128 final MinMax minMax = findMinAndMax(floatPixels); 129 final float near = minMax.min; 130 final float far = minMax.max; 131 DepthTransform transform = new RangeInverseDepthTransform(near, far); 132 133 /* 134 android.util.Log.v("DepthImage", "near = " + String.format("%g", near)); 135 android.util.Log.v("DepthImage", "far = " + String.format("%g", far)); 136 */ 137 int width = pfm.getWidth(); 138 int height = pfm.getHeight(); 139 140 for (int i = 0; i < intPixels.length; i++) { 141 int value = transform.quantize(floatPixels[i]) & 0xFF; 142 intPixels[i] = value | (value << 8) | (value << 16) | (0xFF << 24); 143 /* 144 if (i >= intPixels.length - width) { 145 android.util.Log.v("DepthImage", "float pixel " + i + ":" + String.format("%g", floatPixels[i])); 146 android.util.Log.v("DepthImage", "int pixel " + i + ":" + String.format("0x%02X", intPixels[i])); 147 } 148 */ 149 } 150 151 Bitmap bitmap = Bitmap.createBitmap(intPixels, width, height, Bitmap.Config.ARGB_8888); 152 153 // MediaStoreSaver.savePNG(bitmap, "depthmap", "balls", context); 154 155 return new DepthImage(RangeInverseDepthTransform.FORMAT, 156 far, 157 near, 158 bitmap, // depthmap 159 400.0, // blur at ininity 160 //15.0, // blur at ininity 161 19.6, // focal distance 162 //near+(far-near)*0.2, // focal distance 163 //5.0, // flocal distance 164 0.005, // depth of field 165 0.4, // x of focal point 166 0.4, // y of focal point 167 transform); 168 } 169 getDepthBitmap()170 public Bitmap getDepthBitmap() { 171 return mDepthBitmap; 172 } 173 getDepthTransform()174 public DepthTransform getDepthTransform() { return mDepthTransform; } 175 getFormat()176 public String getFormat() { 177 return mFormat; 178 } 179 getFar()180 public double getFar() { 181 return mFar; 182 } 183 getNear()184 public double getNear() { 185 return mNear; 186 } 187 getBlurAtInfinity()188 public double getBlurAtInfinity() { 189 return mBlurAtInfinity; 190 } 191 getFocalDistance()192 public double getFocalDistance() { 193 return mFocalDistance; 194 } 195 getDepthOfField()196 public double getDepthOfField() {return mDepthOfField; } 197 getFocalPointX()198 public double getFocalPointX() { 199 return mFocalPointX; 200 } 201 getFocalPointY()202 public double getFocalPointY() { 203 return mFocalPointY; 204 } 205 } 206 207