I find myself in need of assistance.
I'm trying to develop this simple app that takes pictures (Wow, now that's original!). Everything is fine. The only thing I need is to have a CIRCULAR CAMERA PREVIEW.
I have my camerapreview class (which extends surfaceview) placed inside a frame layout, which is my camera preview basically. As you all know, this comes in a rectangular shape. Since I have bigger plans for the app, I'd need the camera preview to be circular (so, for example, someone can take a picture of someone's face and I can have some drawings around...).
Now, I don't know how to proceed. I tried different things, creating a shape with xml and set it as background for my frame layout, but that just didn't work.
After hours spent on google for solutions I decided that I had to give up and come here.
So please, if someone knows anything, let us know :) I hope I was clear enough, do not hesitate to ask for clarification if needed.
Simple way:
1) not setup surface for priview
2) catch raw data
3) convert to bitmap and make circle
4) show (for ex. on imegeview)
just for sample:
public class CameraRoundPriview extends ImageView {
private Camera camera;
private Bitmap bitmap = null;
private int mPreviewWidth, mPreviewHeight;
boolean mCameraOn = false;
public CameraRoundPriview(Context context, AttributeSet attrs) {
super(context, attrs);
}
private Bitmap getclip() {
//clip
Bitmap output = Bitmap.createBitmap(bitmap.getHeight(),
bitmap.getHeight(),
Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getHeight(),
bitmap.getHeight());
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
canvas.drawCircle(bitmap.getHeight() / 2,
bitmap.getHeight() / 2,
bitmap.getHeight() / 2, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
//rotate
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(getCameraID(), info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result = degrees;
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP){
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
}
Matrix matrix = new Matrix();
matrix.postRotate(result);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(output,output.getWidth(),output.getHeight(),true);
Bitmap rotatedBitmap = Bitmap.createBitmap(scaledBitmap , 0, 0, scaledBitmap.getWidth(), scaledBitmap .getHeight(), matrix, true);
return rotatedBitmap;
}
private void showImage(){
if ((bitmap != null)){
this.setImageBitmap(getclip());
}
}
public boolean onClickCamera(){
if (mCameraOn){
mCameraOn = false;
cameraStop();
}else{
mCameraOn = true;
cameraStart();
}
return mCameraOn;
}
private void cameraStop(){
if (camera == null) return;
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
private int getCameraID(){
// specify camera id
return 0;
}
private void cameraStart(){
Camera camera = Camera.open(getCameraID());
final Camera.Size previewSize = camera.getParameters().getPreviewSize();
mPreviewWidth = previewSize.width;
mPreviewHeight = previewSize.height;
try {
camera.setPreviewCallback(new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera_call) {
ByteArrayOutputStream outstr = new ByteArrayOutputStream();
Rect rect = new Rect(0, 0, mPreviewWidth, mPreviewHeight);
YuvImage yuvimage=new YuvImage(data,ImageFormat.NV21,mPreviewWidth,mPreviewHeight,null);
yuvimage.compressToJpeg(rect, 50, outstr);
bitmap = BitmapFactory.decodeByteArray(outstr.toByteArray(), 0, outstr.size());
showImage();
camera_call.addCallbackBuffer(data);
}
});
} catch (Exception e) {}
camera.startPreview();
this.camera=camera;
}
}
You can overlay an ImageView
over the camera preview. put both the SurfaceView
and the ImageView
within a FrameLayout
both match_parent
and the image must be on top. Set to an black image with transparent circle in the middle.
this is as simple as shown below: this is for camerax or camera2 API
Note: you must have background transparent.
you must have xml file like below.
<com.RoundedCameraPreview
android:id="@+id/viewFinder"
android:background="#00000000"
app:scaleType="fillCenter"
android:layout_width="match_parent"
android:layout_height="match_parent" />
also don't forget to declare in style.xml
<declare-styleable name="PreviewView">
<attr name="isRound" format="boolean" />
</declare-styleable>
and code is written like this
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.camera.view.PreviewView;
public class RoundedCameraPreview extends PreviewView {
Path clipPath;
boolean isRound;
public RoundedCameraPreview(@NonNull Context context) {
super(context);
}
public RoundedCameraPreview(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public RoundedCameraPreview(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.PreviewView,
0, 0);
try {
isRound = a.getBoolean(R.styleable.PreviewView_isRound, true);
} finally {
a.recycle();
}
}
public boolean isRound() {
return isRound;
}
public void setIsRound(boolean isRound) {
this.isRound = isRound;
invalidate();
requestLayout();
}
public RoundedCameraPreview(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void dispatchDraw(Canvas canvas) {
if (isRound) {
clipPath = new Path();
//TODO: define the circle you actually want
clipPath.addCircle(canvas.getWidth() / 2, canvas.getWidth() / 2, canvas.getWidth() / 2, Path.Direction.CW);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.clipPath(clipPath);
canvas.drawPath(clipPath, paint);
}
super.dispatchDraw(canvas);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.