How to zoom image using Cardboard App
This project aims at developing inexpensive virtual reality (VR) image zoom for everyone on a click of a trigger using the class animation. This project enables users to know about the use of VR Cardboard and its functioning.
Equipment Required – VR Cardboard, NFC enabled device
The following steps involved in the use of VR application for
image zoom functionality are listed below:
Equipment Required – VR Cardboard, NFC enabled device
How to use
the above functionality for end users?
Step 1: Start the application on your mobile devices.
Step 2: The Application will ask the user to put the device into
the cardboard.
Step 3: Pull the magnet to see the images.
Step 4: You will find the image getting changed and zoom on pulling
the magnet each time.
How to
develop this application on Eclipse?
It is very simple for developers to make this application go live.
Follow the below given steps to achieve your goal:
Step 1: Click on New in
the File Menu Bar.
Step 2: Go to the Android
Application Project in the drop down.
Step 3: A pop-up will appear showing the Application Name in which
you have to enter VRImageZoom. Similarly, enter the project name as VRImageZoom, you can also keep a different project name. Similarly, enter the package name as kr.cardboard.imagezoom, this also you can keep with a
different package name.
Step 4: The Minimum Required SDK should be API 16: Android 4.1 (Jelly Bean),
target SDK you can keep as much as you
want.
Step 5: Click the Next
Button thrice and Choose Blank Activity,
again click on Next and enter
Activity Name as VR IMAGE Zoom Activity.
Step 6: Enter Layout Name as main_activity and click on Finish button.
Step 7: Now, download the
cardboard.jar
Step 8: Go to the manifest file to give following permissions:
Ø
<uses-sdk
android:minSdkVersion="16"/> indicates that the device must be running API Level 16
(Jellybean) or higher.
Ø
<uses-sdk
android:targetSdkVersion="19"/> indicates our app is targetting API Level 19 (KitKat).
Ø
<uses-feature
android:glEsVersion="0x00020000" android:required="true"
/> indicates that the
device must support OpenGL ES 2.0 to run the demo app.
Ø
android:screenOrientation="landscape" indicates that the
activity's required screen orientation is "landscape." This is the
orientation you must set for VR apps. The view used by the Cardboard SDK, CardboardView, only renders on fullscreen and
landscape (landscape, reverseLandscape, sensorLandscape) modes.
Ø
android.permission.VIBRATE permission is required by
our demo app to make the phone vibrate to inform the user that something has
happened.
Code as mentioned below-
<?xml version="1.0"
encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="kr.cardboard.imagezoom"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.VIBRATE"
/>
<uses-feature
android:glEsVersion="0x00030000"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="kr.cardboard.imagezoom.VRImageZoomActivity"
android:label="@string/app_name"
android:noHistory="true"
android:screenOrientation="landscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN"
/>
<category android:name="android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
</application>
</manifest>
Step 9: Right click on the source file à New àClass àFile Name CardboardOverlayView
à Finish.
Step 10: Now, extends LinearLayout then create a two view left and right.
Step 11: The following code for the CardboardOverlayView as
follows:
package
kr.cardboard.imagezoom;
import android.content.Context;
import
android.content.Intent;
import
android.graphics.Color;
import
android.graphics.Typeface;
import
android.util.AttributeSet;
import
android.util.TypedValue;
import
android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import
android.view.animation.AlphaAnimation;
import
android.view.animation.Animation;
import
android.view.animation.AnimationUtils;
import
android.widget.ImageView;
import
android.widget.LinearLayout;
import
android.widget.TextView;
/**
* Contains two sub-views to provide a
simple stereo HUD.
*/
public class CardboardOverlayView
extends LinearLayout {
private static final String TAG =
CardboardOverlayView.class
.getSimpleName();
private final
CardboardOverlayEyeView mLeftView;
private final
CardboardOverlayEyeView mRightView;
private AlphaAnimation mTextFadeAnimation;
public
CardboardOverlayView(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(HORIZONTAL);
LayoutParams
params = new
LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT, 1.0f);
params.setMargins(0, 0, 0,
0);
mLeftView = new
CardboardOverlayEyeView(context, attrs);
mLeftView.setLayoutParams(params);
addView(mLeftView);
mRightView = new CardboardOverlayEyeView(context, attrs);
mRightView.setLayoutParams(params);
addView(mRightView);
// Set some
reasonable defaults.
setDepthOffset(0.016f);
setColor(Color.rgb(150,
255, 180));
setVisibility(View.VISIBLE);
mTextFadeAnimation = new AlphaAnimation(1.0f,
0.0f);
mTextFadeAnimation.setDuration(5000);
}
public void show3DSplashImage()
{
setSplashImg();
}
private void setSplashImg() {
mLeftView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mLeftView.imageView.setBackgroundResource(R.drawable.magnet);
mRightView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mRightView.imageView.setBackgroundResource(R.drawable.magnet);
}
public void show3DToast(String message) {
setText(message);
setTextAlpha(1f);
mTextFadeAnimation.setAnimationListener(new
EndAnimationListener() {
@Override
public void
onAnimationEnd(Animation animation) {
setTextAlpha(0f);
}
});
startAnimation(mTextFadeAnimation);
}
public void show3DImage(int mScore, Context context) {
setImg(mScore, context);
}
private abstract class EndAnimationListener
implements
Animation.AnimationListener
{
@Override
public void
onAnimationRepeat(Animation animation) {
}
@Override
public void
onAnimationStart(Animation animation) {
}
}
private void setDepthOffset(float offset) {
mLeftView.setOffset(offset);
mRightView.setOffset(-offset);
}
//
---------------------------------------------------------------------------------------------
private void setImg(int mScore, Context context) {
switch (mScore) {
case 0:
mLeftView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mLeftView.imageView.setBackgroundResource(R.drawable.main);
mRightView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mRightView.imageView.setBackgroundResource(R.drawable.main);
break;
case 1:
Animation
animZoomIn = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in);
mLeftView.imageView.startAnimation(animZoomIn);
mRightView.imageView.startAnimation(animZoomIn);
break;
case 2:
Animation
animZoomIn1 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in1);
mLeftView.imageView.startAnimation(animZoomIn1);
mRightView.imageView.startAnimation(animZoomIn1);
break;
case 3:
mLeftView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mLeftView.imageView.setBackgroundResource(R.drawable.image2);
mRightView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mRightView.imageView.setBackgroundResource(R.drawable.image2);
break;
case 4:
Animation
animZoomIn2 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in);
mLeftView.imageView.startAnimation(animZoomIn2);
mRightView.imageView.startAnimation(animZoomIn2);
break;
case 5:
Animation
animZoomIn3 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in1);
mLeftView.imageView.startAnimation(animZoomIn3);
mRightView.imageView.startAnimation(animZoomIn3);
break;
case 6:
mLeftView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mLeftView.imageView.setBackgroundResource(R.drawable.image3);
mRightView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mRightView.imageView.setBackgroundResource(R.drawable.image3);
break;
case 7:
Animation
animZoomIn4 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in);
mLeftView.imageView.startAnimation(animZoomIn4);
mRightView.imageView.startAnimation(animZoomIn4);
break;
case 8:
Animation
animZoomIn5 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in1);
mLeftView.imageView.startAnimation(animZoomIn5);
mRightView.imageView.startAnimation(animZoomIn5);
break;
case 9:
mLeftView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mLeftView.imageView.setBackgroundResource(R.drawable.image4);
mRightView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mRightView.imageView.setBackgroundResource(R.drawable.image4);
break;
case 10:
Animation
animZoomIn6 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in);
mLeftView.imageView.startAnimation(animZoomIn6);
mRightView.imageView.startAnimation(animZoomIn6);
break;
case 11:
Animation
animZoomIn7 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in1);
mLeftView.imageView.startAnimation(animZoomIn7);
mRightView.imageView.startAnimation(animZoomIn7);
break;
case 12:
mLeftView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mLeftView.imageView.setBackgroundResource(R.drawable.image5);
mRightView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mRightView.imageView.setBackgroundResource(R.drawable.image5);
break;
case 13:
Animation
animZoomIn8 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in);
mLeftView.imageView.startAnimation(animZoomIn8);
mRightView.imageView.startAnimation(animZoomIn8);
break;
case 14:
Animation
animZoomIn9 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in1);
mLeftView.imageView.startAnimation(animZoomIn9);
mRightView.imageView.startAnimation(animZoomIn9);
break;
case 15:
mLeftView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mLeftView.imageView.setBackgroundResource(R.drawable.image6);
mRightView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mRightView.imageView.setBackgroundResource(R.drawable.image6);
break;
case 16:
Animation
animZoomIn10 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in);
mLeftView.imageView.startAnimation(animZoomIn10);
mRightView.imageView.startAnimation(animZoomIn10);
break;
case 17:
Animation
animZoomIn11 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in1);
mLeftView.imageView.startAnimation(animZoomIn11);
mRightView.imageView.startAnimation(animZoomIn11);
break;
case 18:
mLeftView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mLeftView.imageView.setBackgroundResource(R.drawable.image7);
mRightView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mRightView.imageView.setBackgroundResource(R.drawable.image7);
break;
case 19:
Animation
animZoomIn12 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in);
mLeftView.imageView.startAnimation(animZoomIn12);
mRightView.imageView.startAnimation(animZoomIn12);
break;
case 20:
Animation
animZoomIn13 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in1);
mLeftView.imageView.startAnimation(animZoomIn13);
mRightView.imageView.startAnimation(animZoomIn13);
case 21:
mLeftView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mLeftView.imageView.setBackgroundResource(R.drawable.image8);
mRightView.imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mRightView.imageView.setBackgroundResource(R.drawable.image8);
break;
case 22:
Animation
animZoomIn14 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in);
mLeftView.imageView.startAnimation(animZoomIn14);
mRightView.imageView.startAnimation(animZoomIn14);
break;
case 23:
Animation
animZoomIn15 = AnimationUtils.loadAnimation(
context.getApplicationContext(),
R.anim.zoom_in1);
mLeftView.imageView.startAnimation(animZoomIn15);
mRightView.imageView.startAnimation(animZoomIn15);
break;
default:
Intent
intent = new Intent(context,
VRImageZoomActivity.class);
context.startActivity(intent);
}
}
private void setText(String text) {
mLeftView.setText(text);
mRightView.setText(text);
}
private void setTextAlpha(float alpha) {
mLeftView.setTextViewAlpha(alpha);
mRightView.setTextViewAlpha(alpha);
}
private void setColor(int color) {
mLeftView.setColor(color);
mRightView.setColor(color);
}
/**
* A simple view group containing some
horizontally centered text underneath
* a horizontally centered image.
*
* This is a helper class for
CardboardOverlayView.
*/
private class
CardboardOverlayEyeView extends ViewGroup {
private final ImageView imageView;
private final TextView textView;
private float offset;
public
CardboardOverlayEyeView(Context context, AttributeSet attrs) {
super(context, attrs);
imageView = new ImageView(context, attrs);
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setAdjustViewBounds(true); // Preserve aspect
ratio.
addView(imageView);
textView = new TextView(context, attrs);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14.0f);
textView.setTypeface(textView.getTypeface(),
Typeface.BOLD);
textView.setGravity(Gravity.CENTER);
textView.setShadowLayer(3.0f,
0.0f, 0.0f, Color.DKGRAY);
addView(textView);
}
public void setColor(int color) {
//
imageView.setColorFilter(color);
textView.setTextColor(color);
}
public void setText(String text) {
textView.setText(text);
}
public void setTextViewAlpha(float alpha) {
textView.setAlpha(alpha);
}
public void setOffset(float offset) {
this.offset = offset;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
// Width and height
of this ViewGroup.
final int width = right - left;
final int height = bottom - top;
// The size of the
image, given as a fraction of the dimension as a
// ViewGroup. We
multiply
// both width and
heading with this number to compute the image's
// bounding box.
Inside the
// box, the image
is the horizontally and vertically centered.
final float imageSize = 1.0f;
// The fraction of
this ViewGroup's height by which we shift the
// image off the
ViewGroup's
// center. Positive
values shift downwards, negative values shift
// upwards.
final float verticalImageOffset = -0.00f;
// Vertical
position of the text, specified in fractions of this
// ViewGroup's
height.
final float verticalTextPos = 0.52f;
// Layout ImageView
float imageMargin = (1.0f - imageSize) / 2.0f;
float leftMargin = (int) (width * (imageMargin + offset));
float topMargin = (int) (height * (imageMargin + verticalImageOffset));
imageView.layout((int) leftMargin, (int) topMargin,
(int) (leftMargin + width * imageSize),
(int) (topMargin + height * imageSize));
// Layout TextView
leftMargin = offset * width;
topMargin = height * verticalTextPos;
textView.layout((int) leftMargin, (int) topMargin,
(int) (leftMargin + width), (int) (topMargin + height
*
(1.0f - verticalTextPos)));
}
}
}
In the above code, we have extended the linear layout and created
a function with function name show3DImage to make
the view more clear and visible.
Step 12: The Cardboard provide its own view named as CardboardView, which is a convenience extension of GLSurfaceView
that is used for VR rendering. Now, you can see how to define a CardboardView
in the activity layout xml file along with our CardboardOverlayView in the
following way:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ui_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<com.google.vrtoolkit.cardboard.CardboardView
android:id="@+id/cardboard_view1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
/>
<kr.cardboard.imagezoom.CardboardOverlayView
android:id="@+id/overlay"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
/>
</RelativeLayout>
Step 13: Open the class VRImageZoomActivity as defined below:
Cardboard Activity is the starting point for coding a cardboard app.CardboardActivity is the base activity that provides easy integration with Cardboard devices. It exposes events to interact with Cardboards and handles many of the details commonly required when creating an activity for VR rendering.
Note that CardboardActivity uses sticky immersive mode, in which the system UI is hidden, and the content takes up the whole screen. This is a requirement for a VR app, since CardboardView will only render when the activity is in fullscreen mode. See Using Immersive Full-Screen Mode for more discussion of this feature.
The demo app's MainActivity extends CardboardActivity. MainActivity implements the following interface:
CardboardView.StereoRenderer: Interface for renderers that delegate all stereoscopic rendering details to the view. Implementors should simply render a view as they would normally do using the provided transformation parameters. All stereoscopic rendering and distortion correction details are abstracted from the renderer and managed internally by the view.
Step 14: Initializes the CardboardView in the onCreate() method:
/**
* Sets the view to our CardboardView
and initializes the transformation matrices we will use
* to render our scene.
* @param savedInstanceState
*/
@Override
public void onCreate(Bundle
savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.common_ui);
CardboardView cardboardView = (CardboardView)
findViewById(R.id.cardboard_view);
//
Associate a CardboardView.StereoRenderer with cardboardView.
cardboardView.setRenderer(this);
//
Associate the cardboardView with this activity.
setCardboardView(cardboardView);
//
Initialize other objects here.
}
Step 14: Once you get the CardboardView you associate it with a renderer, and then you associate the CardboardView with the activity.
Step 15: Now define CardboardOverlayView class as-
CardboardOverlayView mOverlayView =(CardboardOverlayView)findViewById(R.id.overlay);
Step 16: Now, how to use magnet –
To provide custom behavior when the user pulls the magnet, override CardboardActivity.onCardboardTrigger() in your app's activity.
Call the show3d Image.
@Override
public
void onCardboardTrigger() {
Log.i(TAG,
"onRendererShutdown1");
mOverlayView.show3DImage(mScore++,VRImageZoomActivity.this);
mVibrator.vibrate(50);
}
Now, please go through the whole code as mentioned below:
package
kr.cardboard.imagezoom;
import
javax.microedition.khronos.egl.EGLConfig;
import
android.content.Context;
import
android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Vibrator;
import android.util.Log;
import
android.widget.ImageView;
import
com.google.vrtoolkit.cardboard.CardboardActivity;
import
com.google.vrtoolkit.cardboard.CardboardView;
import
com.google.vrtoolkit.cardboard.EyeTransform;
import
com.google.vrtoolkit.cardboard.HeadTransform;
import
com.google.vrtoolkit.cardboard.Viewport;
/**
* A Cardboard sample application.
*/
public class VRImageZoomActivity extends CardboardActivity implements
CardboardView.StereoRenderer
{
private static final String TAG = "MainActivity2";
Uri
fileUri = null;
ImageView
photoImage = null;
private Vibrator mVibrator;
private int mScore = 0;
private CardboardOverlayView
mOverlayView;
public
VRImageZoomActivity() {
}
/**
* Sets the view to our CardboardView and
initializes the transformation
* matrices we will use to render our scene.
//@param savedInstanceState
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
CardboardView
cardboardView = (CardboardView)
findViewById(R.id.cardboard_view1);
cardboardView.setRenderer(this);
setCardboardView(cardboardView);
mVibrator = (Vibrator)
getSystemService(Context.VIBRATOR_SERVICE);
mOverlayView =
(CardboardOverlayView) findViewById(R.id.overlay);
mOverlayView.show3DSplashImage();
}
protected void onNfcIntent(Intent intent) {
}
@Override
public void onRendererShutdown()
{
Log.i(TAG, "onRendererShutdown");
}
@Override
public void onSurfaceChanged(int width, int height) {
Log.i(TAG, "onSurfaceChanged");
}
@Override
public boolean isDeviceInCardboard()
{
Log.d("isDeviceInCardboard", "isDeviceInCardboard");
return false;
}
/**
* Creates the buffers we use to store
information about the 3D world.
* OpenGL doesn't use Java arrays, but rather
needs data in a format it can
* understand. Hence we use ByteBuffers.
*
* @param config
*
The EGL configuration used when creating the surface.
*/
@Override
public void
onSurfaceCreated(EGLConfig config) {
Log.i(TAG, "onSurfaceCreated");
}
@Override
public void onCardboardTrigger()
{
Log.i(TAG, "onRendererShutdown1");
mOverlayView.show3DImage(mScore++,
VRImageZoomActivity.this);
mVibrator.vibrate(50);
}
/**
* Prepares OpenGL ES before we draw a frame.
*
* @param headTransform
*
The head transformation in the new frame.
*/
@Override
public void
onNewFrame(HeadTransform headTransform) {
}
/**
* Draws a frame for an eye. The transformation
for that eye (from the
* camera) is passed in as a parameter.
*
* @param transform
*
The transformations to apply to
render this eye.
*/
@Override
public void
onDrawEye(EyeTransform transform) {
}
@Override
public void
onFinishFrame(Viewport viewport) {
}
public void
onRemovedFromCardboard() {
Log.d("vbv", "msg");
}
}
is there a zoom out function available in this code ... if so kindly mention it
ReplyDeleteis there a zoom out function available in this code ... if so kindly mention it
ReplyDeleteHi, could you explain more about Zoom function?
ReplyDelete