1package com.android.rs.refocus; 2 3import android.content.ContentResolver; 4import android.content.Context; 5import android.graphics.Bitmap; 6import android.graphics.BitmapFactory; 7import android.graphics.Color; 8import android.net.Uri; 9import android.util.Log; 10 11import java.io.FileNotFoundException; 12import java.io.IOException; 13 14/** 15 * An RGBZ image, where Z stands for depth, i.e. a color+depth image. 16 * The RGBZ always has a preview image, which represents the latest rendering of the RGBZ. 17 * The preview is encoded as the normal jpeg content for client compatibility, 18 * while the color channel and depth channels are encoded as XMP data. 19 * The class supports lazy initialization where the XMP meta data is loaded only when first 20 * accessed. 21 * 22 * @author chernand@google.com (Carlos Hernandez) 23 */ 24public class RGBZ { 25 public static final String TAG = "RGBZ"; 26 27 private Bitmap bitmap; 28 private Bitmap preview; 29 private Bitmap depthBitmap; 30 private DepthTransform depthTransform; 31 private DepthImage depthImage; 32 33 /** 34 * Creates an RGBZ from a content uri. 35 * 36 * @param uri The uri name of the RGBZ 37 * @throws FileNotFoundException if the RGBZ could not be read 38 */ 39 public RGBZ(Uri uri, ContentResolver contentResolver, Context context) throws IOException { 40 preview = BitmapFactory.decodeStream(contentResolver.openInputStream(uri)); 41 if (preview == null) { 42 throw new FileNotFoundException(uri.toString()); 43 } 44 this.depthImage = new DepthImage(context, uri); 45 this.depthBitmap = depthImage.getDepthBitmap(); 46 this.bitmap = setAlphaChannel(preview, this.depthBitmap); 47 this.depthTransform = depthImage.getDepthTransform(); 48 } 49 50 /** 51 * @return Whether the RGBZ has a depth channel 52 */ 53 public boolean hasDepthmap() { 54 return depthTransform != null; 55 } 56 57 /** 58 * @return The color+depth {@code Bitmap} 59 */ 60 public Bitmap getBitmap() { 61 return bitmap; 62 } 63 64 /** 65 * @return The depthmap component of this RGBZ 66 */ 67 public DepthTransform getDepthTransform() { 68 return depthTransform; 69 } 70 71 public double getFocusDepth() { 72 return this.depthImage.getFocalDistance(); 73 } 74 75 public double getDepthOfField() { 76 return this.depthImage.getDepthOfField(); 77 } 78 79 public double getBlurInfinity() { 80 return this.depthImage.getBlurAtInfinity(); 81 } 82 83 /** 84 * @return the width of this {@code RGBZ} 85 */ 86 public int getWidth() { 87 return bitmap.getWidth(); 88 } 89 90 /** 91 * @return the height of this {@code RGBZ} 92 */ 93 public int getHeight() { 94 return bitmap.getHeight(); 95 } 96 97 /** 98 * @return the depth value of the given pixel 99 */ 100 101 public float getDepth(int x, int y) { 102 if (!hasDepthmap()) { 103 return 0.0f; 104 } 105 if (x < 0 || x > depthBitmap.getWidth() || 106 y < 0 || y > depthBitmap.getHeight()) { 107 Log.e("RGBZ getDepth", "index out of bound"); 108 return 0; 109 } 110 return getDepthTransform().reconstruct(Color.blue(depthBitmap.getPixel(x, y))); 111 } 112 113 /** 114 * Sets the depthmap as the alpha channel of the {@code Bitmap}. 115 */ 116 public Bitmap setAlphaChannel(Bitmap bitmap, Bitmap depthBitmap) { 117 if (bitmap == null) { 118 return bitmap; 119 } 120 Bitmap result = bitmap.copy(Bitmap.Config.ARGB_8888, true); 121 // set the alpha channel of depthBitmap to alpha of bitmap 122 result = setAlphaChannelFromBitmap(depthBitmap, bitmap, result); 123 return result; 124 } 125 126 private Bitmap setAlphaChannelFromBitmap(Bitmap depth, Bitmap orig, Bitmap dest) { 127 int w = orig.getWidth(); 128 int h = orig.getHeight(); 129 int[] orig_data = new int[w*h]; 130 int[] depth_data = new int[w*h]; 131 132 orig.getPixels(orig_data, 0, w, 0, 0, w, h); 133 depth.getPixels(depth_data, 0, w, 0, 0, w, h); 134 for (int i = 0; i < orig_data.length; i++) { 135 int v = orig_data[i] & 0x00FFFFFF; 136 int temp = (depth_data[i] & 0x000000FF) << 24; 137 v = v | temp; 138 orig_data[i] = v; 139 } 140 dest.setPixels(orig_data, 0, w, 0, 0, w, h); 141 return dest; 142 } 143} 144 145