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