How To Make Square Camera Bellows
Hey, if yous didn't already know, I'k currently working on an open world stealth exploration game called Farewell North in my spare time, which is available to wishlist on Steam!
Foursquare photos are all the rage now since Instagram introduced them back in 2010, but implementing them on Android is much more than painful than you'd imagine.
The Camera API on Android supports very little native functionality for foursquare photos, limiting you to the resolutions that the camera supports, which varies from device to device. None of the devices I've tested back up a native 1:1 aspect ratio, so merely resizing the image to a foursquare, or showing the camera preview as a square, will leave you with badly stretched images.
Luckily, foursquare photos are achievable using the following steps:
- Display a fullscreen camera preview with non-transparent overlays to make it look square.
- When the photo is taken, crop the section of the image that matches your square preview.
Unfortunately this requires a lot more work than y'all'd imagine, so let's get started:
Foursquare Preview
We want the preview to look as though it'due south a square, then that when the user takes a photograph it matches the preview. In order to accomplish this, we overlay views on top of the photographic camera preview to make it look square:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- Camera Preview --> <SurfaceView android:id="@+id/camera_preview" android:layout_width="match_parent" android:layout_height="match_parent"/> <!-- /Stop Camera Preview --> <!-- Overlay --> <RelativeLayout android:id="@+id/overlay" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/white" android:layout_alignParentBottom="true"> <!--- Put your Content Here ---> </RelativeLayout> <!-- /End Overlay --> </RelativeLayout>
Y'all can see nosotros make the SurfaceView (our photographic camera preview) friction match the full width and peak of the layout, taking up the full screen. Nosotros use a RelativeLayout every bit the parent so we can then create an overlay view, here another RelativeLayout, and align information technology to the bottom of the parent, on top of the preview. It'southward important to now that you can put anything in the overlay, such every bit a push to take a photo. The content doesn't thing, it just matters that it takes up surface area to cover the preview.
Subsequently that, in our Activity, we set the elevation of the overlay so that it fills enough of the screen to make the preview appear to be square. We practise that by setting the top equal to the height of the preview, minus the width.
Square Preview
private class SquareCameraActivity extends Activity { private SurfaceView cameraPreview; individual RelativeLayout overlay; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Optional: Hibernate the status bar at the top of the window requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // Ready the content view and get references to our views setContentView(R.layout.square_camera); cameraPreview = (SurfaceView) findViewById(R.id.camera_preview); overlay = (RelativeLayout) findViewById(R.id.overlay); } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); // Get the preview size int previewWidth = cameraPreview.getMeasuredWidth(), previewHeight = cameraPreview.getMeasuredHeight(); // Set the height of the overlay and so that it makes the preview a foursquare RelativeLayout.LayoutParams overlayParams = (RelativeLayout.LayoutParams) overlay.getLayoutParams(); overlayParams.top = previewHeight - previewWidth; overlay.setLayoutParams(overlayParams); } } At present our view contains a "foursquare" camera preview with a bottom overlay that can contain your buttons and other UI elements.
Foursquare Photos
With our square preview, we're ready to start taking photos. The problem is that the preview is unrelated to the last product - just considering we have a square preview, doesn't mean we'll have a foursquare pic. What we'll have to do is ingather the picture when information technology's taken to match the preview.
For this, I've plant that trying to match the preview size with the motion picture size is going to aid become the closest possible match. Afterwards you initialize your camera, effort to match the preview and picture sizes to a value that is greater than the size of the square we desire:
Camera camera = Photographic camera.open up(Camera.CameraInfo.CAMERA_FACING_BACK); Photographic camera.Parameters camParams = camera.getParameters(); // Discover a preview size that is at least the size of our IMAGE_SIZE Camera.Size previewSize = camParams.getSupportedPreviewSizes().become(0); for (Camera.Size size : camParams.getSupportedPreviewSizes()) { if (size.width >= IMAGE_SIZE && size.height >= IMAGE_SIZE) { previewSize = size; interruption; } } camParams.setPreviewSize(previewSize.width, previewSize.meridian); // Try to discover the closest picture size to match the preview size. Camera.Size pictureSize = camParams.getSupportedPictureSizes().get(0); for (Camera.Size size : camParams.getSupportedPictureSizes()) { if (size.width == previewSize.width && size.pinnacle == previewSize.height) { pictureSize = size; break; } } camParams.setPictureSize(pictureSize.width, pictureSize.height); First we find a preview size that the camera supports, who'southward width and height are at least equal to the IMAGE_SIZE that we want. IMAGE_SIZE tin can exist any integer, but know that the higher the value, the less probable nosotros are to notice a lucifer. I've constitute that 1024 is a skilful value for large images, that is supported by near devices. Once we've found an acceptable preview size, we set information technology on the camera parameters.
Next we look at the cameras supported picture sizes - the size of the actual pictures that tin be taken. We effort to notice an exact match to the preview size we discovered, which I've constitute in about cases is available. It is possible that there is no picture size that matches the preview size, so in this case we default to the first movie size. Again once nosotros've constitute the right picture size, we set it on the photographic camera parameters.
You tin can get-go the preview and handle permissions in accordance with the Android Programmer Guide, simply once information technology comes to handling the captured photo, we have one more than thing nosotros demand to practise.
With the byte array returned from the camera picture callback, we need to procedure the image in such a way that it crops a foursquare from the height of the prototype, since the top of the preview is all that'due south displayed to the user. If we were to cut a foursquare out of the eye of the paradigm, it wouldn't friction match the preview.
The processing code looks like then:
private Bitmap processImage(byte[] data) throws IOException { // Determine the width/height of the image int width = camera.getParameters().getPictureSize().width; int height = camera.getParameters().getPictureSize().peak; // Load the bitmap from the byte array BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_8888; Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options); // Rotate and crop the image into a foursquare int croppedWidth = (width > height) ? height : width; int croppedHeight = (width > height) ? tiptop : width; Matrix matrix = new Matrix(); matrix.postRotate(IMAGE_ORIENTATION); Bitmap cropped = Bitmap.createBitmap(bitmap, 0, 0, croppedWidth, croppedHeight, matrix, true); bitmap.recycle(); // Scale down to the output size Bitmap scaledBitmap = Bitmap.createScaledBitmap(cropped, IMAGE_SIZE, IMAGE_SIZE, true); cropped.recycle(); return scaledBitmap; } Note: You lot'll notice an IMAGE_ORIENTATION value here when we rotate the image. Because the camera we're making hither is vertical, when initializing the photographic camera nosotros tell information technology to rotate ninety degrees when displaying in the preview. The resulting image is as well going to need to be rotated to be vertical, so in this case IMAGE_ORIENTATION is 90. It's important to annotation still that this is non the all-time way to accomplish this, and you should detect and alter the camera preview orientation and image processing rotation, programmatically at runtime based on the camera of the device you're running on. Information technology's unsafe to assume that all devices will be handled by a directly ninety-degree rotation. For more information on how to exercise this, encounter the setDisplayOrientation sample code.
Calling this from the onPictureTaken event of the Camera.PictureCallback interface will give united states of america a perfectly square image that matches the preview displayed to the user.
Preview
Issue
Summary
And that's how yous handle creating a square camera on Android. When I first approached this, I had assumed that there would be built-in functionality to handle square photos, especially with how popular they've get in recent years, so I was surprised how much needed to become into this seemingly trivial task.
I didn't cover the nuts of setting upwardly your camera, creating the holder, handling permissions and rotation, and all the other goodies that get forth with camera management, but combining this post with the Android Developer Guide should get yous exactly where you desire with regards to taking square photos on Android!
Source: https://kylewbanks.com/blog/tutorial-square-camera-with-preview-on-android
Posted by: colewittionfer.blogspot.com

0 Response to "How To Make Square Camera Bellows"
Post a Comment