Home | History | Annotate | Download | only in refocus
      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    */
     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    */
     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    */
     87   public boolean hasDepthmap() {
     88     return depthTransform != null;
     89   }
     90 
     91   /**
     92    * @return The color+depth {@code Bitmap}
     93    */
     94   public Bitmap getBitmap() {
     95     return bitmap;
     96   }
     97 
     98   /**
     99    * @return The depthmap component of this RGBZ
    100    */
    101   public DepthTransform getDepthTransform() {
    102     return depthTransform;
    103   }
    104 
    105   public double getFocusDepth() {
    106     return this.depthImage.getFocalDistance();
    107   }
    108 
    109   public double getDepthOfField() {
    110     return this.depthImage.getDepthOfField();
    111   }
    112 
    113   public double getBlurInfinity() {
    114     return this.depthImage.getBlurAtInfinity();
    115   }
    116 
    117   /**
    118    * @return the width of this {@code RGBZ}
    119    */
    120   public int getWidth() {
    121     return bitmap.getWidth();
    122   }
    123 
    124   /**
    125    * @return the height of this {@code RGBZ}
    126    */
    127   public int getHeight() {
    128     return bitmap.getHeight();
    129   }
    130 
    131   /**
    132    * @return the depth value of the given pixel
    133    */
    134 
    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    */
    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 
    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