Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get bitmap from surfaceView?

I want to capture bitmap image from custom surfaceView. and I try to setBitmapImage in imageView.

But, the surfaceView saves nothing.

Here is my Android code:

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    OurSurface ourSurface;
    FrameLayout surfaceLayout;
    ImageView layoutCaptured;
    Button capture;

    Bitmap bitmap;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        layoutCaptured = (ImageView)findViewById(R.id.layoutCaptured);
        surfaceLayout = (FrameLayout)findViewById(R.id.surfaceLayout);
        capture = (Button)findViewById(R.id.capture);
        capture.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                surfaceLayout.setDrawingCacheEnabled(true);
                surfaceLayout.buildDrawingCache(true);
                Bitmap bmp = Bitmap.createBitmap(surfaceLayout.getDrawingCache());

                surfaceLayout.setDrawingCacheEnabled(false);

                layoutCaptured.setImageBitmap(bmp);

                Log.d("MainActivity", "onClick -> setImageBitmap");
            }
        });

        ourSurface = new OurSurface(this);
        surfaceLayout.addView(ourSurface);

    }

    @Override
    protected void onResume() {
        super.onResume();
        ourSurface.resume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        ourSurface.pause();
    }

    public class OurSurface extends SurfaceView implements Runnable{
        public OurSurface(Context context) {
            super(context);
            init(context);
        }

        public OurSurface(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }

        Thread thread;
        SurfaceHolder holder;
        boolean isItOK;
        Canvas canvas;
        int x1,y1,x2,y2,x3,y3;
        Paint red, green, blue;

        public void init(Context context){
            holder = getHolder();

            red = new Paint(Paint.ANTI_ALIAS_FLAG);
            red.setColor(Color.RED);
            red.setStyle(Paint.Style.FILL);
            green = new Paint(Paint.ANTI_ALIAS_FLAG);
            green.setColor(Color.GREEN);
            green.setStyle(Paint.Style.FILL);
            blue = new Paint(Paint.ANTI_ALIAS_FLAG);
            blue.setColor(Color.BLUE);
            blue.setStyle(Paint.Style.FILL);
        }

        public void resume(){
            isItOK = true;
            thread = new Thread(this);
            thread.start();
        }

        public void pause(){
            isItOK = false;
            while(true){
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                thread = null;
                break;
            }
        }

        int width, height;
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            width = w;
            height = h;
            Log.d("onSizeChanged", "width #"+width+", height #"+height);
            bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            canvas = new Canvas(bitmap);
        }

        int x1Sign = 1, y1Sign = 1, x2Sign = 1, y2Sign = 1, x3Sign = 1, y3Sign = 1;
        @Override
        public void run() {
            while(isItOK == true){
                if(!holder.getSurface().isValid()){
                    continue;
                }
                canvas = holder.lockCanvas();

                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

                if(x1 > width) { x1 = width; x1Sign = (-1)*x1Sign; }
                else if(x1 < 0) { x1 = 0; x1Sign = (-1)*x1Sign; }
                if(y1 > height) { y1 = height; y1Sign = (-1)*y1Sign; }
                else if(y1 < 0) { y1 = 0; y1Sign = (-1)*y1Sign; }

                if(x2 > width) { x2 = width; x2Sign = (-1)*x2Sign; }
                else if(x2 < 0) { x2 = 0; x2Sign = (-1)*x2Sign; }
                if(y2 > height) { y2 = height; y2Sign = (-1)*y2Sign; }
                else if(y2 < 0) { y2 = 0; y2Sign = (-1)*y2Sign; }

                if(x3 > width) { x3 = width; x3Sign = (-1)*x3Sign; }
                else if(x3 < 0) { x3 = 0; x3Sign = (-1)*x3Sign; }
                if(y3 > height) { y3 = height; y3Sign = (-1)*y3Sign; }
                else if(y3 < 0) { y3 = 0; y3Sign = (-1)*y3Sign; }



                x1 = x1 + 1*x1Sign;
                y1 = y1 + 3*y1Sign;

                x2 = x2 + 2*x2Sign;
                y2 = y2 + 2*y2Sign;

                x3 = x3 + 3*x3Sign;
                y3 = y3 + 1*y3Sign;

                canvas.drawCircle(x1, y1, 10, red);
                canvas.drawCircle(x2, y2, 10, green);
                canvas.drawCircle(x3, y3, 10, blue);

                holder.unlockCanvasAndPost(canvas);
            }
        }
    }

}

and, activity_main.xml code.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"
    android:orientation="vertical"
    android:weightSum="2">


    <LinearLayout
        android:weightSum="5"
        android:orientation="vertical"
        android:id="@+id/mainLayout"
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="fill_parent">

        <Button
            android:layout_weight="1"
            android:text="capture"
            android:id="@+id/capture"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <ImageView
            android:id="@+id/layoutCaptured"
            android:layout_weight="4"
            android:layout_width="match_parent"
            android:layout_height="fill_parent">

        </ImageView>
    </LinearLayout>

    <FrameLayout
        android:id="@+id/surfaceLayout"
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="fill_parent">
    </FrameLayout>



</LinearLayout>

Please let me know.

like image 934
bubu uwu Avatar asked Oct 14 '15 08:10

bubu uwu


People also ask

How to get Bitmap from SurfaceView in Android?

There is no simple way to capture frames of SurfaceView, so you can consider using TextureView instead of SurfaceView: the Bitmap can be retrieved using textureView. getBitmap() method.

Is drawing cache enabled deprecated?

getDrawingCache() has been deprecated.

What is a surface in Android?

Surface objects enable apps to render images to be presented on screens. SurfaceHolder interfaces enable apps to edit and control surfaces.


1 Answers

It seems, that it isn't possible to get the bitmap of the SurfaceView directly.

In fact, there are cases where the display data for the SurfaceView isn't even accessible to the app processor - it may be the output of a hardware video pipeline that is composited with the display output of the app processor through a dedicated video overlay. 1

In your case it would be possible to draw the canvas to a bitmap, the usual recipe is 2:

  1. Create a bitmap of the correct size using Bitmap.createBitmap()
  2. Create a canvas instance pointing that this bitmap using Canvas(Bitmap) constructor
  3. Draw to the canvas
  4. Use the bitmap

UPDATE

After some research it "could" be work by doing this:

public Bitmap getBitmap() {
    setDrawingCacheEnabled(true);
    buildDrawingCache(true);
    final Bitmap bitmap = Bitmap.createBitmap( getDrawingCache() );
    setDrawingCacheEnabled(false);
    destroyDrawingCache();
    return bitmap;
}

A project about it, can be found here.

like image 98
Manuel Schmitzberger Avatar answered Sep 30 '22 12:09

Manuel Schmitzberger