blob: 1e42bf132c5ad198edd6c9f025c2d99ceb0b9843 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.renderscript.cts.refocus;
import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.renderscript.cts.refocus.image.RangeInverseDepthTransform;
import android.util.Log;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* An RGBZ image, where Z stands for depth, i.e. a color+depth image.
* The RGBZ always has a preview image, which represents the latest rendering of the RGBZ.
* The preview is encoded as the normal jpeg content for client compatibility,
* while the color channel and depth channels are encoded as XMP data.
* The class supports lazy initialization where the XMP meta data is loaded only when first
* accessed.
*/
public class RGBZ {
public static final String TAG = "RGBZ";
private Bitmap bitmap;
private Bitmap preview;
private Bitmap depthBitmap;
private DepthTransform depthTransform;
private DepthImage depthImage;
/**
* Creates an RGBZ from a content uri.
*
* @param uri The uri name of the RGBZ
* @throws FileNotFoundException if the RGBZ could not be read
*/
public RGBZ(Uri uri, ContentResolver contentResolver, Context context) throws IOException {
preview = BitmapFactory.decodeStream(contentResolver.openInputStream(uri));
if (preview == null) {
throw new FileNotFoundException(uri.toString());
}
depthImage = DepthImage.createFromXMPMetadata(context, uri);
depthBitmap = depthImage.getDepthBitmap();
bitmap = setAlphaChannel(preview, depthBitmap);
depthTransform = depthImage.getDepthTransform();
}
/**
* Creates an RGBZ from uris to an image and a depthmap.
*
* @param uriImage The uri name of the image
* @param uriDepthmap The uri name of the depthmap
* @throws FileNotFoundException if the RGBZ could not be read
*/
public RGBZ(Uri uriImage, Uri uriDepthmap, ContentResolver contentResolver,
Context context) throws IOException {
preview = BitmapFactory.decodeStream(contentResolver.openInputStream(uriImage));
if (preview == null) {
throw new FileNotFoundException(uriImage.toString());
}
depthImage = DepthImage.createFromDepthmap(context, uriDepthmap);
depthBitmap = depthImage.getDepthBitmap();
bitmap = setAlphaChannel(preview, depthBitmap);
depthTransform = depthImage.getDepthTransform();
}
/**
* @return Whether the RGBZ has a depth channel
*/
public boolean hasDepthmap() {
return depthTransform != null;
}
/**
* @return The color+depth {@code Bitmap}
*/
public Bitmap getBitmap() {
return bitmap;
}
/**
* @return The depthmap component of this RGBZ
*/
public DepthTransform getDepthTransform() {
return depthTransform;
}
public double getFocusDepth() {
return this.depthImage.getFocalDistance();
}
public double getDepthOfField() {
return this.depthImage.getDepthOfField();
}
public double getBlurInfinity() {
return this.depthImage.getBlurAtInfinity();
}
/**
* @return the width of this {@code RGBZ}
*/
public int getWidth() {
return bitmap.getWidth();
}
/**
* @return the height of this {@code RGBZ}
*/
public int getHeight() {
return bitmap.getHeight();
}
/**
* @return the depth value of the given pixel
*/
public float getDepth(int x, int y) {
if (!hasDepthmap()) {
return 0.0f;
}
if (x < 0 || x > depthBitmap.getWidth() ||
y < 0 || y > depthBitmap.getHeight()) {
Log.e("RGBZ getDepth", "index out of bound");
return 0;
}
return getDepthTransform().reconstruct(Color.blue(depthBitmap.getPixel(x, y)));
}
/**
* Sets the depthmap as the alpha channel of the {@code Bitmap}.
*/
public Bitmap setAlphaChannel(Bitmap bitmap, Bitmap depthBitmap) {
if (bitmap == null) {
return bitmap;
}
Bitmap result = bitmap.copy(Bitmap.Config.ARGB_8888, true);
// set the alpha channel of depthBitmap to alpha of bitmap
result = setAlphaChannelFromBitmap(depthBitmap, bitmap, result);
return result;
}
private Bitmap setAlphaChannelFromBitmap(Bitmap depth, Bitmap orig, Bitmap dest) {
int w = orig.getWidth();
int h = orig.getHeight();
int[] orig_data = new int[w*h];
int[] depth_data = new int[w*h];
orig.getPixels(orig_data, 0, w, 0, 0, w, h);
depth.getPixels(depth_data, 0, w, 0, 0, w, h);
for (int i = 0; i < orig_data.length; i++) {
int v = orig_data[i] & 0x00FFFFFF;
int temp = (depth_data[i] & 0x000000FF) << 24;
v = v | temp;
orig_data[i] = v;
}
dest.setPixels(orig_data, 0, w, 0, 0, w, h);
return dest;
}
}