How to set the size of the camera’s preview in a square squared SurfaceView (e.g. Instagram)

I am trying to develop my own work with the camera, but I have a problem that I cannot solve ...

What I want is very similar to creating a photo frame, and here is what I get:

My image

When I get something like this:

Instagram image

and...

My second image

when should i get something like:

Instagram 2

I think I'm good at previewing SurfaceView and Camera previews only using

Camera.Parameters parameters = camera.getParameters(); camera.setDisplayOrientation(90); 

and Custom SurfaceView:

 public class SquaredSurfaceView extends SurfaceView { private int width; private int height; public SquaredSurfaceView(Context context) { super(context); } public SquaredSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); } public SquaredSurfaceView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = MeasureSpec.getSize(widthMeasureSpec); height = width; setMeasuredDimension(width, width); } public int getViewWidth() { return width; } public int getViewHeight() { return height; } 

}

What am I doing wrong?: - (

+45
android camera surfaceview
Jun 20 2018-12-12T00:
source share
6 answers

As already mentioned, you need to find the correct preview size (one that has an aspect ratio of 1: 1), and you probably need to use FrameLayout for SurfacePreview. It seems that you have a problem with the aspect ratio, maybe you have the correct preview size, but you put it in the wrong layout.

Another solution could be (like Instagram) to make your camera full size, and then hide some areas of the layour to make it look like a square. Then, using software, you have to cut out the image to make it real.

Hope this helps you

+16
03 Oct
source share

The solution that works for me is the 2nd answer, but because we need to rotate the camera 90 °, we need to switch WIDTH with HEIGTH, something like this ...

  camera.setDisplayOrientation(90); Camera.Parameters params= camera.getParameters(); surfaceView.getLayoutParams().width=params.getPreviewSize().height; surfaceView.getLayoutParams().height=params.getPreviewSize().width; 

Hope this solution helps !: D

+5
May 31 '13 at 1:15
source share

my solution is more like creating a square mask and then placing it on top of the preview surface.

You will need 3 things basically, first the square component of the frame. I created a custom component:

 package com.example.squaredviewer; import android.content.Context; import android.util.AttributeSet; import android.view.Display; import android.view.WindowManager; import android.widget.RelativeLayout; /** * Created by yadirhb on 14-08-2015. */ public class SquaredFrame extends RelativeLayout{ public SquaredFrame(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int size = Math.min(getMeasuredWidth(), getMeasuredHeight()); setMeasuredDimension(size, size); } } 

Depending on the version of the Android API you are developing for, you may need to add another constructor overload. For Kitkat, this is wonderful.

The second step is to create a layout:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:visibility="visible"> <RelativeLayout android:id="@+id/camera_preview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="false" android:layout_alignParentTop="false" android:layout_centerInParent="true" android:background="#ffffff"> </RelativeLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:background="#131008"> </LinearLayout> <com.example.squaredviewer.SquaredFrame android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true"></com.example.squaredviewer.SquaredFrame> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:background="#131008" /> </LinearLayout> </RelativeLayout> 

Note that the RelativeLayout "camera_preview" is the one used to render the preview, it is centered and has a LinearLayout that contains the square of the component. This is actually a “mask” and it covers the preview of the camera. Also note that besides the transparent SquaredFrame, the other two are the background color with black.

Now a surface view for a camera preview in which the surface size matches the format.

 public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private final String TAG = "PIC-FRAME"; private SurfaceHolder mHolder; private Camera mCamera; private Display display; public CameraPreview(Activity context, Camera camera) { super(context); mCamera = camera; display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); // deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); setKeepScreenOn(true); } public void surfaceDestroyed(SurfaceHolder holder) { // empty. Take care of releasing the Camera preview in your activity. this.getHolder().removeCallback(this); } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. if (mHolder.getSurface() == null) { // preview surface does not exist return; } try { // stop preview before making changes mCamera.stopPreview(); // set preview size and make any resize, rotate or // reformatting changes here // Now that the size is known, set up the camera parameters and begin // the preview. Camera.Parameters parameters = mCamera.getParameters(); // You need to choose the most appropriate previewSize for your app Camera.Size previewSize = parametes.getSupportedPreviewSizes().get(0); parameters.setPreviewSize(previewSize.width, previewSize.height); // start preview with new settings mCamera.setParameters(parameters); // Set the holder size based on the aspect ratio int size = Math.min(display.getWidth(), display.getHeight()); double ratio = (double) previewSize.width / previewSize.height; mHolder.setFixedSize((int)(size * ratio), size); mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e) { Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } } } } 

Now everything should be connected with the activity class.

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_picture_taker); mDecorView = getWindow().getDecorView(); //mCamera = a camera instance; // Create our Preview view and set it as the content of our activity. mPreview = new CameraPreview(this, mCamera); //Layout where camera preview is shown. RelativeLayout preview = (RelativeLayout) findViewById(R.id.camera_preview); //FrameLayout stack controllers inside and superpose them. preview.addView(mPreview, 0); // TODO } 

A little long, but I hope it will be useful for a few. :-)

+2
Aug 16 '15 at 19:05
source share

I had the same problem with the square view - it solved it simply by setting the size of the SurfaceView camera to the size of the view where I wanted to draw it. No complicated calculations, and it works for me. See my answer here for the whole method: stack overflow

 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { ... params.setPreviewSize(viewParams.height, viewParams.width); camera.setParameters(params); 
+2
Sep 10 '16 at 10:12
source share

You can use this to get pictureSize:

 public static void initialCameraPictureSize(Context context, android.hardware.Camera.Parameters parameters) { List list = parameters.getSupportedPictureSizes(); if(list != null) { android.hardware.Camera.Size size = null; Iterator iterator = list.iterator(); do { if(!iterator.hasNext()) break; android.hardware.Camera.Size size1 = (android.hardware.Camera.Size)iterator.next(); if(Math.abs(3F * ((float)size1.width / 4F) - (float)size1.height) < 0.1F * (float)size1.width && (size == null || size1.height > size.height && size1.width < 3000)) size = size1; } while(true); if(size != null) parameters.setPictureSize(size.width, size.height); else Log.e("CameraSettings", "No supported picture size found"); } } 
0
May 09 '13 at 18:29
source share

It is so complicated. Not easy.

First: you define 2 black Linear Layout to get the user interface when publishing.

Second: you need to crop the image from the full image to a square image.

How to cut, you need to use the scaleBitmap method.

Or do you want a real custom camera? Can check here

-one
Dec 03 '15 at 9:24
source share



All Articles