Android uses SurfaceView to display Camera image climbing pit (2)

Preface

The previous chapter “[Android uses SurfaceView to display Camera image climbing pit record (1) We have realized the use of SurfaceView to display the real-time frame images in the Camera. The main directory we do this is to take out the data of each frame After image processing by OpenCV, the processed image is displayed in real time.

To achieve this, we first need to store the real-time data of the Camera as Bitbmp images and then display them through our own processing. Next, we will see how to display the real-time images of the Camera through Bitbmp.

Code Implementation

Let’s continue with the code from the previous article. Remember the callback method of Camera defined in our VaccaeSurfaceView class in the previous article?

We can view the log in the LogCat after the program runs, and the good string will be sent continuously in the input Log, as shown in the figure below

The above shows that our callback method has been successful. Thinking of displaying the image processing by ourselves, we can process the image in this callback method.

Here is a brief introduction to the synchronized(this) in the code. When two concurrent threads access the synchronized(this) synchronization code block in the same object, only one thread can be executed at a time. Another thread must wait for the current thread to finish executing the code block before executing the code block.

Simply speaking, each frame of image we acquire will be processed in this code before processing the next frame of image. Of course, AnsycTask can also be used here.

Implementation principle and core code

We press the obtained picture Bitbmp on the image to generate Canavas through the SurfaceHolder we created, and then draw the picture in this Canavas through the method of drawBitbmp.

Code of the callback function

 private Camera.PreviewCallback previewCallback=new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] bytes, Camera camera) {
            synchronized (this) {
                Log.i("frame", "good");
                int width=camera.getParameters().getPreviewSize().width;
                int height=camera.getParameters().getPreviewSize().height;
                Canvas canvas = holder. lockCanvas();
                if (canvas != null) {
                    canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
                    Bitmap cacheBitmap=nv21ToBitmap(bytes, width, height);
                    canvas. drawBitmap(cacheBitmap, 0, 0, null);
                    holder.unlockCanvasAndPost(canvas);
                }
            }
        }
    };

In the above figure, there is a nv21toBitmap method for images, which is used to generate images. Let’s take a look at this method.

nv21ToBitmap

 // output image
    private static Bitmap nv21ToBitmap(byte[] nv21, int width, int height) {
        Bitmap bitmap=null;
        try {
            YuvImage image=new YuvImage(nv21, ImageFormat.NV21, width, height, null);
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            image.compressToJpeg(new Rect(0, 0, width, height), 80, stream);
            //Convert rawImage to bitmap
            BitmapFactory.Options options=new BitmapFactory.Options();
            options.inPreferredConfig=Bitmap.Config.ARGB_8888;
            bitmap=BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size(), options);

            stream. close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

So far, it seems that we have completed it. Then we run the program, and the program has been running normally, but we looked at the records in LogCat and found that it keeps reporting errors.

I searched for the reason on the Internet. It may be that there is a problem with the sentence camera.setPreviewDisplay(holder). The camera has been using this holder to output images like a surfaceview. Later in the program, the surfaceholder is used to draw a new picture, which will conflict and report an error.

After looking for a solution, I found that SurfaceTexture can be used instead to realize the drawing of this image, so let’s try this method

First define a SurfaceTexture

Then instantiate this SurfaceTexture in the VaccaeSurfaceView constructor

Finally, add setPreviewTexture to the method of StartCamera, and block the original method of seetPreviewDisplay

Next, after we run the program, we find that every frame is also displayed, but the direction of the image is wrong, as shown below

Solving this problem is also relatively simple. Let’s modify our nv21ToBitmap method of processing pictures and let it be rotated 90 degrees directly.

nv21ToBitmap

 private static Bitmap nv21ToBitmap(byte[] nv21, int width, int height) {
        Bitmap bitmap=null;
        try {
            YuvImage image=new YuvImage(nv21, ImageFormat.NV21, width, height, null);
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            image.compressToJpeg(new Rect(0, 0, width, height), 80, stream);
            //Convert rawImage to bitmap
            BitmapFactory.Options options=new BitmapFactory.Options();
            options.inPreferredConfig=Bitmap.Config.ARGB_8888;
            bitmap=BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size(), options);

            // add image rotation
            Matrix m = new Matrix();
            m. postRotate(90);
            bitmap=Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
                    m, true);

            stream. close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

Video effect of our rerun program

As you can see from the above video, our image is normal, but the size displayed by the image is inconsistent with our interface layout. We will focus on this problem in the next article to see how to deal with it.

Last

More Android learning materials can be scanned for free!

“Android Programming Beginner’s Guide” + Android Basic Course Pack

Summary of contents: Android programming guide, Android basic course information package;

Content features: clear organization, including graphic representation, which is easier to understand;

How to get the complete document

# **”Android Programming Guide”**

Table of Contents

img

Chapter 1 Basics of Java language from entry to familiarity

? ● Overview of Java

? ● Basics of Java

? ● class

? ● object-oriented

? ● container

? ● multi-threaded

? ● IO

? ● regular expressions

? Calendar

? ● Annotation usage and simple instructions

? ● Java uses encryption algorithms

img

Chapter 2 Kotlin language basics from entry to familiarity

? ● Introduction to the Kotlin series

? ● New project

? ● Concept introduction

? ● common wording

? lambda

? ● higher-order functions

? ● extension functions

? ● Coroutines

img

Chapter 3 Android technology stack from entry to familiarity

? ● start

? ● Activity

? ● Service service

? ● Broadcast mechanism

? ● Fragment

? ● res application resources

? ● Permissions

? ● TextView display text

? ● EditText user input

? ● Button button

? ● ImageView image display

? ● Layout

? ● DrawerLayout Side Slider

? ● RecyclerView display list

? ● multi-threaded

? ● I/O operations

? Storage

? ● NetWork network

? ● ProgressBar progress bar

? View

? ● Custom View

? ● animation

? WebView

? ● StatusBar

? ● Camera

? ● Media

? ● Bluetooth Bluetooth

? ● WiFi connection

? ● Get the current angle of the phone

? ● launcher

? ● AIDL

? zip

? ● Binder

? ● Notification Notification

? ● Package Manager

? ● RTFSC

? ● design pattern

? ● Third-party libraries

? Android Studio

? ● Modular

? Gradle

? ● NDK

? ● debugging

img

Chapter 4 Android Jetpack family bucket comprehensive learning