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 17package com.android.rs.refocus; 18 19import android.content.Context; 20import android.graphics.Bitmap; 21import android.graphics.BitmapFactory; 22import android.net.Uri; 23import com.android.rs.refocus.image.RangeInverseDepthTransform; 24import com.android.rs.refocus.image.RangeLinearDepthTransform; 25import java.io.FileNotFoundException; 26import java.io.IOException; 27import java.io.InputStream; 28 29public 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 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 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 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 98 public MinMax(float min, float max) { 99 this.min = min; 100 this.max = max; 101 } 102 103 public static MinMax create(float min, float max) { 104 return new MinMax(min, max); 105 } 106 } 107 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 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 170 public Bitmap getDepthBitmap() { 171 return mDepthBitmap; 172 } 173 174 public DepthTransform getDepthTransform() { return mDepthTransform; } 175 176 public String getFormat() { 177 return mFormat; 178 } 179 180 public double getFar() { 181 return mFar; 182 } 183 184 public double getNear() { 185 return mNear; 186 } 187 188 public double getBlurAtInfinity() { 189 return mBlurAtInfinity; 190 } 191 192 public double getFocalDistance() { 193 return mFocalDistance; 194 } 195 196 public double getDepthOfField() {return mDepthOfField; } 197 198 public double getFocalPointX() { 199 return mFocalPointX; 200 } 201 202 public double getFocalPointY() { 203 return mFocalPointY; 204 } 205} 206 207