Skip to content

Instantly share code, notes, and snippets.

@moshimore
Created September 15, 2019 15:11
Show Gist options
  • Save moshimore/e8a473cfbbf4ee87a04ea39c88dc69a6 to your computer and use it in GitHub Desktop.
Save moshimore/e8a473cfbbf4ee87a04ea39c88dc69a6 to your computer and use it in GitHub Desktop.
Android CameraX Sample

Android CameraX Sample

The sample source was only Kotlin, so I rewrite it in Java. Operation has been verified with the actual machine and API 28 emulator. Please give the camera permission to the application from the Android settings.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextureView
android:id="@+id/textureView"
android:layout_width="480px"
android:layout_height="640px"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0" />
<ImageView
android:id="@+id/imageView"
android:layout_width="480px"
android:layout_height="640px"
android:layout_margin="16dp"
app:srcCompat="@mipmap/ic_launcher"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textureView" />
<ImageButton
android:id="@+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:srcCompat="@android:drawable/ic_menu_camera"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
android {
compileSdkVersion 29
defaultConfig {
minSdkVersion 21
targetSdkVersion 29
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
def camerax_version = "1.0.0-alpha05"
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
}
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.*;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Bundle;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import java.nio.ByteBuffer;
public class MainActivity extends AppCompatActivity
{
private TextureView textureView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textureView = findViewById(R.id.textureView);
textureView.post((Runnable)(new Runnable()
{
public final void run()
{
startCamera();
}
}));
textureView.addOnLayoutChangeListener(new View.OnLayoutChangeListener()
{
@Override
public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)
{
updateTransform();
}
});
}
private void startCamera()
{
PreviewConfig.Builder previewConfig = new PreviewConfig.Builder();
Preview preview = new Preview(previewConfig.build());
preview.setOnPreviewOutputUpdateListener(new Preview.OnPreviewOutputUpdateListener()
{
@Override
public void onUpdated(Preview.PreviewOutput output)
{
ViewGroup parent = (ViewGroup) textureView.getParent();
parent.removeView(textureView);
parent.addView(textureView, 0);
textureView.setSurfaceTexture(output.getSurfaceTexture());
updateTransform();
}
});
ImageCaptureConfig.Builder imageCaptureConfig = new ImageCaptureConfig.Builder();
final ImageCapture imageCapture = new ImageCapture(imageCaptureConfig.build());
ImageButton button = findViewById(R.id.imageButton);
button.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
imageCapture.takePicture(new ImageCapture.OnImageCapturedListener()
{
@Override
public void onCaptureSuccess(ImageProxy image, int rotationDegrees)
{
ImageView imageView = findViewById(R.id.imageView);
imageView.setImageBitmap(imageProxyToBitmap(image));
imageView.setRotation(rotationDegrees);
image.close();
}
});
}
});
CameraX.bindToLifecycle(this, preview, imageCapture);
}
private void updateTransform()
{
Matrix matrix = new Matrix();
float centerX = textureView.getWidth() / 2f;
float centerY = textureView.getHeight() / 2f;
float rotationDegrees = 0f;
switch (textureView.getDisplay().getRotation())
{
case Surface.ROTATION_0:
rotationDegrees = 0f;
break;
case Surface.ROTATION_90:
rotationDegrees = 90f;
break;
case Surface.ROTATION_180:
rotationDegrees = 180f;
break;
case Surface.ROTATION_270:
rotationDegrees = 270f;
break;
default:
return;
}
matrix.postRotate(-rotationDegrees, centerX, centerY);
textureView.setTransform(matrix);
}
private Bitmap imageProxyToBitmap(ImageProxy image)
{
ImageProxy.PlaneProxy planeProxy = image.getPlanes()[0];
ByteBuffer buffer = planeProxy.getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment