ArViewer  Android Version
Arvos - Augmented reality viewer open source
 All Classes Namespaces Files Functions Variables
ArvosCameraView.java
Go to the documentation of this file.
1 /*
2  Copyright (C) 2013, Peter Graf
3 
4  This file is part of Arvos - AR Viewer Open Source for Android.
5  Arvos is free software.
6 
7  This program is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program. If not, see <http://www.gnu.org/licenses/>.
19 
20  For more information on the AR Viewer Open Source or Peter Graf,
21  please see: http://www.mission-base.com/.
22  */
23 
24 package com.mission_base.arviewer_android.viewer;
25 
26 import java.util.List;
27 
28 import android.content.Context;
29 import android.hardware.Camera;
30 import android.hardware.Camera.Size;
31 import android.util.Log;
32 import android.view.SurfaceHolder;
33 import android.view.SurfaceView;
34 
35 import com.mission_base.arviewer_android.Arvos;
36 
43 public class ArvosCameraView extends SurfaceView implements SurfaceHolder.Callback
44 {
45  private static String mTag = "ArvosCameraView";
46  private SurfaceHolder mHolder;
47  private Camera mCamera;
48 
55  @SuppressWarnings("deprecation")
56  ArvosCameraView(Context context)
57  {
58  super(context);
59  Log.d(mTag, "ArvosCameraView()");
60 
61  // Install a SurfaceHolder.Callback so we get notified when the
62  // underlying surface is created and destroyed.
63  mHolder = getHolder();
64  mHolder.addCallback(this);
65  mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
66  }
67 
68  public void surfaceCreated(SurfaceHolder holder)
69  {
70  Log.d(mTag, "surfaceCreated");
71  try
72  {
73  if (mCamera != null)
74  {
75  mCamera.release();
76  }
77 
78  // The Surface has been created, acquire the camera and tell it
79  // where to draw.
80  mCamera = Camera.open();
81  mCamera.setPreviewDisplay(holder);
82  }
83  catch (Exception e)
84  {
85  Log.d(mTag, e.getMessage());
86  }
87  }
88 
89  public void surfaceDestroyed(SurfaceHolder holder)
90  {
91  Log.d(mTag, "surfaceDestroyed");
92  try
93  {
94  // Surface will be destroyed when we return, so stop the preview.
95  // Because the CameraDevice object is not a shared resource, it's
96  // very important to release it when the activity is paused.
97  mCamera.stopPreview();
98  mCamera.release();
99  mCamera = null;
100  }
101  catch (Exception e)
102  {
103  Log.d(mTag, e.getMessage());
104  }
105  }
106 
107  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
108  {
109  Log.d(mTag, "surfaceChanged");
110  try
111  {
112  // Now that the size is known, set up the camera parameters and
113  // begin the preview.
114  Camera.Parameters parameters = mCamera.getParameters();
115 
116  Size previewSize = getOptimalPreviewSize(parameters.getSupportedPreviewSizes(), w, h);
117 
118  parameters.setPreviewSize(previewSize.width, previewSize.height);
119  mCamera.setParameters(parameters);
120  setCameraDisplayOrientation(0, mCamera);
121  }
122  catch (Exception e)
123  {
124  Log.d(mTag, e.getMessage());
125  }
126  Log.d(mTag, "startPreview");
127  try
128  {
129  mCamera.startPreview();
130  }
131  catch (Exception e)
132  {
133  Log.d(mTag, e.getMessage());
134  }
135  }
136 
137  private static void setCameraDisplayOrientation(int cameraId, Camera camera)
138  {
139  Camera.CameraInfo info = new Camera.CameraInfo();
140  Camera.getCameraInfo(cameraId, info);
141 
142  int degrees = Arvos.getInstance().getRotationDegrees();
143  // Log.d(mTag, "RotationDegrees = " + degrees);
144 
145  int result;
146  if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
147  {
148  result = (info.orientation + degrees) % 360;
149  result = (360 - result) % 360; // compensate the mirror
150  }
151  else
152  { // back-facing
153  result = (info.orientation - degrees + 360) % 360;
154  }
155  camera.setDisplayOrientation(result);
156  }
157 
158  private static Size getOptimalPreviewSize(List<Size> sizes, int w, int h)
159  {
160  final double ASPECT_TOLERANCE = 0.1;
161  double targetRatio = (double) w / h;
162  if (sizes == null)
163  return null;
164 
165  Size optimalSize = null;
166  double minDiff = Double.MAX_VALUE;
167 
168  int targetHeight = h;
169 
170  // Try to find an size match aspect ratio and size
171  for (Size size : sizes)
172  {
173  double ratio = (double) size.width / size.height;
174  if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
175  continue;
176  if (Math.abs(size.height - targetHeight) < minDiff)
177  {
178  optimalSize = size;
179  minDiff = Math.abs(size.height - targetHeight);
180  }
181  }
182 
183  // Cannot find the one match the aspect ratio, ignore the requirement
184  if (optimalSize == null)
185  {
186  minDiff = Double.MAX_VALUE;
187  for (Size size : sizes)
188  {
189  if (Math.abs(size.height - targetHeight) < minDiff)
190  {
191  optimalSize = size;
192  minDiff = Math.abs(size.height - targetHeight);
193  }
194  }
195  }
196  return optimalSize;
197  }
198 }