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.
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.
getDrawingCache() has been deprecated.
Surface objects enable apps to render images to be presented on screens. SurfaceHolder interfaces enable apps to edit and control surfaces.
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:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With