如何使用 CameraSource 拍照?
Posted
技术标签:
【中文标题】如何使用 CameraSource 拍照?【英文标题】:How to take a photo using CameraSource? 【发布时间】:2017-12-26 19:27:12 【问题描述】:当我想使用相机拍照时,CameraSource 出现了一些问题。 我想要的只是用我在 xml 文件上制作的按钮拍照并使用“CameraSource”拍照,因为我也在使用“TextRecognizer”。 相机工作正常,但是当我按下按钮拍照时出现问题。
清单文件:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
我的变量:
SurfaceView cameraView;
TextView textView;
CameraSource camera_source;
final int RequestCameraPermissionID = 1001;
类:
// Starting the CameraSource. This will be in the 'OnCreate' function. This function works.
private void OpenCameraSource()
final TextRecognizer textRecognizer = new TextRecognizer.Builder(getApplicationContext()).build();
if (!textRecognizer.isOperational())
Log.w("Steal_Activity", "Detector activity are not yet available");
Toast.makeText(getApplicationContext(),"Detector activity are not yet available",Toast.LENGTH_SHORT).show();
else
camera_source = new CameraSource.Builder(getApplicationContext(),textRecognizer)
.setFacing(CameraSource.CAMERA_FACING_BACK)
.setRequestedPreviewSize(1280, 1024)
.setRequestedFps(2.0f)
.setAutoFocusEnabled(true)
.build();
cameraView.getHolder().addCallback(new SurfaceHolder.Callback()
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder)
try
if (ActivityCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(Steal.this,
new String[]android.Manifest.permission.CAMERA,
RequestCameraPermissionID);
return;
camera_source.start(cameraView.getHolder());
catch (IOException ex)
ex.printStackTrace();
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2)
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder)
camera_source.stop();
);
textRecognizer.setProcessor(new Detector.Processor<TextBlock>()
// Some Stuff here
);
// This function will be launched when the button is pressed
public void OnClick_TakeShot(View view)
try//I GET ERROR HERE
camera_source.takePicture(null,pictureCallback);
catch (Exception ex)
Toast.makeText(getApplicationContext(),"Error:"+ex.toString(),Toast.LENGTH_LONG).show();
// Callback for 'takePicture'
CameraSource.PictureCallback pictureCallback = new CameraSource.PictureCallback()
@Override
public void onPictureTaken(byte[] bytes)
File file_image = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES+"/pics");
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes , 0, bytes .length);
if(bitmap!=null)
if(!file_image.isDirectory())
file_image.mkdir();
file_image=new File(file_image,"mylastpic.jpg");
try
FileOutputStream fileOutputStream=new FileOutputStream(file_image);
bitmap.compress(Bitmap.CompressFormat.JPEG,100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
catch(Exception exception)
Toast.makeText(getApplicationContext(),"Error saving: "+ exception.toString(),Toast.LENGTH_LONG).show();
;
当我按下按钮拍照时不工作
【问题讨论】:
您是在尝试使用其他应用拍照还是尝试制作相机应用? 一个可以使用播放服务读取文本并拍照的相机应用,但我想使用CameraSource
而不是Intent
方法。
从表面上看,OnClick_TakeShot() 中的 camera_source 为空。要么你没有调用 OpenCameraSource(),要么它默默地失败了。
【参考方案1】:
尝试使用这种方式(我正在使用来自 Google Vision 的 OCR 并使用 CameraSource 拍照)Pd:闪光灯按钮我还没有修复它......
您必须使用:在您的依赖项中编译“com.google.android.gms:play-services-vision:9.2.1”以实现 OCR 兼容性
public class CustomCamaraActivity extends BaseActivity implements Callback,
OnClickListener
private Context context;
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private Camera camera;
private Button flipCamera;
private Button flashCameraButton;
private Button captureImage;
private Button BtnCapturarFoto;
private int cameraId;
private boolean flashmode = false;
private int rotation;
private ActionBar actionBar;
private CameraSource cameraSource;
private StringBuilder builder;
private TextView txTextoCapturado;
private static CustomCamaraActivity instance;
private Activity activity;
private String nombreProyecto;
public static final int REQUEST_IMAGE_CAPTURE = 0020;
private File file;
private String ubicacion;
private static final String TAG = "FOTOGRAFIA";
private int Height = 620, Width = 480;
private TextRecognizer recognizer;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_camara_layout);
context = this;
// camera surface view created
cameraId = CameraInfo.CAMERA_FACING_BACK;
flipCamera = (Button) findViewById(R.id.flipCamera);
flashCameraButton = (Button) findViewById(R.id.flash);
captureImage = (Button) findViewById(R.id.captureImage);
BtnCapturarFoto = (Button) findViewById(R.id.btnCapturarFoto);
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
txTextoCapturado = (TextView) findViewById(R.id.tvTextoCapturado);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
flipCamera.setOnClickListener(this);
captureImage.setOnClickListener(this);
flashCameraButton.setOnClickListener(this);
BtnCapturarFoto.setOnClickListener(this);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
/*if (Camera.getNumberOfCameras() > 1)
flipCamera.setVisibility(View.VISIBLE);
*/
if (!getBaseContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA_FLASH))
flashCameraButton.setVisibility(View.GONE);
flipCamera.setVisibility(View.GONE);
recognizer = new TextRecognizer.Builder(getApplicationContext()).build();
if (recognizer.isOperational())
cameraSource = new CameraSource.Builder(getApplicationContext(), recognizer)
.setFacing(CameraSource.CAMERA_FACING_BACK)
.setRequestedPreviewSize(1280, 1024)
.setRequestedFps(15.0f)
.setAutoFocusEnabled(true)
.build();
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback()
@Override
public void surfaceCreated(SurfaceHolder holder)
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(CustomCamaraActivity.this, new String[]Manifest.permission.CAMERA, 100);
return;
try
releaseCamera();
cameraSource.start(surfaceView.getHolder());
catch (IOException e)
e.printStackTrace();
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
@Override
public void surfaceDestroyed(SurfaceHolder holder)
if(cameraSource != null)
cameraSource.stop();
);
recognizer.setProcessor(new Detector.Processor<TextBlock>()
@Override
public void release()
@Override
public void receiveDetections(Detector.Detections<TextBlock> detections)
final SparseArray<TextBlock> items = detections.getDetectedItems();
if (items.size() != 0)
builder = new StringBuilder();
for (int i = 0; i < items.size(); i++)
TextBlock it = items.valueAt(i);
builder.append(it.getValue());
final String read = builder.toString().trim();
//String read = builder.toString().trim().replace(" ", "").replace("\n", "");
try
runOnUiThread(new Runnable()
@Override
public void run()
txTextoCapturado.setText(read);
);
catch (Exception ex)
Log.e("error","Error al actualizar texto OCR");
//It continues doing other things here
);
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
switch (requestCode)
case 100:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
try
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
return;
cameraSource.start(surfaceView.getHolder());
catch (IOException e)
e.printStackTrace();
break;
public String getUbicacion()
return ubicacion;
@Override
protected void onResume()
super.onResume();
@Override
protected void onPause()
super.onPause();
if (camera != null)
camera.setPreviewCallback(null);
camera.setErrorCallback(null);
camera.stopPreview();
camera.release();
camera = null;
@Override
public void onBackPressed()
super.onBackPressed();
if(camera != null)
camera.setPreviewCallback(null);
camera.setErrorCallback(null);
camera.stopPreview();
camera.release();
camera = null;
@Override
public void surfaceCreated(SurfaceHolder holder)
if (!openCamera(CameraInfo.CAMERA_FACING_BACK))
alertCameraDialog();
private boolean openCamera(int id)
boolean result = false;
cameraId = id;
//releaseCamera();
try
camera = Camera.open(cameraId);
catch (Exception e)
e.printStackTrace();
if (camera != null)
try
setUpCamera(camera);
camera.setErrorCallback(new ErrorCallback()
@Override
public void onError(int error, Camera camera)
);
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
result = true;
catch (IOException e)
e.printStackTrace();
result = false;
releaseCamera();
return result;
private void setUpCamera(Camera c)
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
rotation = getWindowManager().getDefaultDisplay().getRotation();
int degree = 0;
switch (rotation)
case Surface.ROTATION_0:
degree = 0;
break;
case Surface.ROTATION_90:
degree = 90;
break;
case Surface.ROTATION_180:
degree = 180;
break;
case Surface.ROTATION_270:
degree = 270;
break;
default:
break;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
// frontFacing
rotation = (info.orientation + degree) % 330;
rotation = (360 - rotation) % 360;
else
// Back-facing
rotation = (info.orientation - degree + 360) % 360;
c.setDisplayOrientation(rotation);
Parameters params = c.getParameters();
showFlashButton(params);
List<String> focusModes = params.getSupportedFlashModes();
if (focusModes != null)
if (focusModes
.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
params.setFlashMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
params.setRotation(rotation);
private void showFlashButton(Parameters params)
boolean showFlash = (getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA_FLASH) && params.getFlashMode() != null)
&& params.getSupportedFlashModes() != null
&& params.getSupportedFocusModes().size() > 1;
flashCameraButton.setVisibility(showFlash ? View.VISIBLE
: View.INVISIBLE);
private void releaseCamera()
try
if (camera != null)
camera.setPreviewCallback(null);
camera.setErrorCallback(null);
camera.stopPreview();
camera.release();
camera = null;
catch (Exception e)
e.printStackTrace();
Log.e("error", e.toString());
camera = null;
private void releaseCameraSource()
try
if (cameraSource != null)
cameraSource.stop();
cameraSource.release();
cameraSource = null;
catch (Exception e)
e.printStackTrace();
Log.e("error", e.toString());
cameraSource = null;
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
@Override
public void surfaceDestroyed(SurfaceHolder holder)
@Override
public void onClick(View v)
switch (v.getId())
case R.id.flash:
flashOnButton();
break;
case R.id.flipCamera:
flipCamera();
break;
case R.id.captureImage:
takeImage();
break;
case R.id.btnCapturarFoto:
takeImage();
break;
default:
break;
private void takeImage()
try
//openCamera(CameraInfo.CAMERA_FACING_BACK);
//releaseCameraSource();
//releaseCamera();
//openCamera(CameraInfo.CAMERA_FACING_BACK);
//setUpCamera(camera);
//Thread.sleep(1000);
cameraSource.takePicture(null, new CameraSource.PictureCallback()
private File imageFile;
@Override
public void onPictureTaken(byte[] bytes)
try
// convert byte array into bitmap
Bitmap loadedImage = null;
Bitmap rotatedBitmap = null;
loadedImage = BitmapFactory.decodeByteArray(bytes, 0,
bytes.length);
// rotate Image
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(rotation);
rotatedBitmap = Bitmap.createBitmap(loadedImage, 0, 0,
loadedImage.getWidth(), loadedImage.getHeight(),
rotateMatrix, false);
String state = Environment.getExternalStorageState();
File folder = null;
if (state.contains(Environment.MEDIA_MOUNTED))
folder = new File(Environment
.getExternalStorageDirectory() + "/Demo");
else
folder = new File(Environment
.getExternalStorageDirectory() + "/Demo");
boolean success = true;
if (!folder.exists())
success = folder.mkdirs();
if (success)
java.util.Date date = new java.util.Date();
imageFile = new File(folder.getAbsolutePath()
+ File.separator
//+ new Timestamp(date.getTime()).toString()
+ "Image.jpg");
imageFile.createNewFile();
else
Toast.makeText(getBaseContext(), "Image Not saved",
Toast.LENGTH_SHORT).show();
return;
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
// save image into gallery
rotatedBitmap = resize(rotatedBitmap, 800, 600);
rotatedBitmap.compress(CompressFormat.JPEG, 100, ostream);
FileOutputStream fout = new FileOutputStream(imageFile);
fout.write(ostream.toByteArray());
fout.close();
ContentValues values = new ContentValues();
values.put(Images.Media.DATE_TAKEN,
System.currentTimeMillis());
values.put(Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.DATA,
imageFile.getAbsolutePath());
CustomCamaraActivity.this.getContentResolver().insert(
Images.Media.EXTERNAL_CONTENT_URI, values);
setResult(Activity.RESULT_OK); //add this
finish();
catch (Exception e)
e.printStackTrace();
);
catch (Exception ex)
txTextoCapturado.setText("Error al capturar fotografia!");
private void flipCamera()
int id = (cameraId == CameraInfo.CAMERA_FACING_BACK ? CameraInfo.CAMERA_FACING_FRONT
: CameraInfo.CAMERA_FACING_BACK);
if (!openCamera(id))
alertCameraDialog();
private void alertCameraDialog()
AlertDialog.Builder dialog = createAlert(CustomCamaraActivity.this,
"Camera info", "error to open camera");
dialog.setNegativeButton("OK", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
dialog.cancel();
);
dialog.show();
private Builder createAlert(Context context, String title, String message)
AlertDialog.Builder dialog = new AlertDialog.Builder(
new ContextThemeWrapper(context,
android.R.style.Theme_Holo_Light_Dialog));
dialog.setIcon(R.drawable.ic_launcher);
if (title != null)
dialog.setTitle(title);
else
dialog.setTitle("Information");
dialog.setMessage(message);
dialog.setCancelable(false);
return dialog;
private void flashOnButton()
if (camera != null)
try
Parameters param = camera.getParameters();
if (flashmode)
param.setFlashMode(Parameters.FLASH_MODE_OFF);
flashCameraButton.setBackground(getResources().getDrawable(R.drawable.ic_flash_off));
else
param.setFlashMode(Parameters.FLASH_MODE_TORCH);
flashCameraButton.setBackground(getResources().getDrawable(R.drawable.ic_flash_on));
//param.setFlashMode(!flashmode ? Parameters.FLASH_MODE_TORCH : Parameters.FLASH_MODE_OFF);
camera.setParameters(param);
flashmode = !flashmode;
catch (Exception e)
e.printStackTrace();
// TODO: handle exception
/**
* Metodo para cambiar el tamaño de la fotografia una resolucion predeterminada.
*
* @param image
* @param maxWidth
* @param maxHeight
* @return
*/
private Bitmap resize(Bitmap image, int maxWidth, int maxHeight)
if (maxHeight > 0 && maxWidth > 0)
int width = image.getWidth();
int height = image.getHeight();
float ratioBitmap = (float) width / (float) height;
float ratioMax = (float) maxWidth / (float) maxHeight;
int finalWidth = maxWidth;
int finalHeight = maxHeight;
if (ratioMax > 1)
finalWidth = (int) ((float) maxHeight * ratioBitmap);
else
finalHeight = (int) ((float) maxWidth / ratioBitmap);
image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true);
return image;
else
return image;
这是布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_ >
<SurfaceView
android:id="@+id/surfaceView"
android:layout_
android:layout_ />
<LinearLayout
android:layout_
android:layout_
android:orientation="vertical"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
<TextView
android:id="@+id/tvTextoCapturado"
android:layout_
android:layout_
android:gravity="center"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_
android:layout_
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="10dp"
android:elevation="0dp"
android:orientation="horizontal"
android:weightSum="30">
<Button
android:id="@+id/flash"
android:layout_
android:layout_
android:layout_alignBaseline="@+id/captureImage"
android:layout_alignBottom="@+id/captureImage"
android:layout_marginLeft="27dp"
android:layout_marginRight="27dp"
android:layout_toLeftOf="@+id/captureImage"
android:layout_toStartOf="@+id/captureImage"
android:layout_weight="4"
android:background="@drawable/ic_flash_off"
android:gravity="center" />
<Button
android:id="@+id/captureImage"
android:layout_
android:layout_
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginLeft="27dp"
android:layout_marginRight="27dp"
android:layout_weight="10"
android:background="@android:drawable/ic_menu_camera"
android:visibility="gone" />
<Button
android:id="@+id/btnCapturarFoto"
style="@style/blue_button"
android:layout_
android:layout_
android:layout_marginLeft="27dp"
android:layout_marginRight="27dp"
android:layout_weight="20"
android:elevation="0dp"
android:text="Tomar fotografia" />
<Button
android:id="@+id/flipCamera"
android:layout_
android:layout_
android:layout_alignParentBottom="true"
android:layout_marginLeft="27dp"
android:layout_marginRight="27dp"
android:layout_toRightOf="@id/captureImage"
android:layout_weight="4"
android:background="@drawable/ic_rotate"
android:visibility="invisible" />
</LinearLayout>
【讨论】:
【参考方案2】:你可以像这样通过 CameraSource 类来实现它:
mCameraSource = builder
.setFlashMode(if (useFlash) Camera.Parameters.FLASH_MODE_TORCH else null)
.build()
将以下代码添加到按钮点击监听器:
mCameraSource.takePicture(null, CameraSource.PictureCallback data ->
// here data is a byteArray, you can play with it :)
【讨论】:
【参考方案3】:您必须将 XML 对象“SurfaceView”添加到您的活动中,而不是将其声明为变量:
在你的 main_activity.xml 中
<SurfaceView
android:id="@+id/cameraView"
android:layout_
android:layout_ />
在你的activity.kt中
val cameraView: SurfaceView = findViewById(R.id.cameraView)
【讨论】:
以上是关于如何使用 CameraSource 拍照?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Android 视觉 CameraSource 中添加放大/缩小手势
如何更改像 setPreviewSize 和 PictureSize 这样的 CameraSource 大小
如何在适用于 Android 的 Google API 的 CameraSource 中保存带有叠加层的图像?