‏إظهار الرسائل ذات التسميات Android code sample: bitmap and image. إظهار كافة الرسائل
‏إظهار الرسائل ذات التسميات Android code sample: bitmap and image. إظهار كافة الرسائل

السبت، 15 مارس 2014

Draw bitmap programmatically for SurfaceView

This exercise create Bitmap programmatically, then draw the bitmap on SurfaceView by calling canvas.drawBitmap().

Draw bitmap programmatically for SurfaceView


I show two approachs in the example:
  • prepareBitmap_A:
    - Create a array of int, fill in data point-by-point, then createBitmap from the array.
  • prepareBitmap_B:
    - Create a bitmap, then fill in pixels by calling setPixel.

I also add code to display the (approximate) processing time in various steps for reference. The videos on the bottom show the result.

MySurfaceView.java
package com.example.androidsurfaceview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MySurfaceView extends SurfaceView {

private SurfaceHolder surfaceHolder;
private MyThread myThread;

MainActivity mainActivity;

long timeStart;
long timeA;
long timeB;
long timeFillBackground;
long timeDrawBitmap;
long timeTotal;

long numberOfPt;

public MySurfaceView(Context context) {
super(context);
init(context);
}

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

public MySurfaceView(Context context,
AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}

private void init(Context c){
mainActivity = (MainActivity)c;
numberOfPt = 0;
myThread = new MyThread(this);

surfaceHolder = getHolder();


surfaceHolder.addCallback(new SurfaceHolder.Callback(){

@Override
public void surfaceCreated(SurfaceHolder holder) {
myThread.setRunning(true);
myThread.start();
}

@Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
// TODO Auto-generated method stub

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
myThread.setRunning(false);
while (retry) {
try {
myThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}});
}

private Bitmap prepareBitmap_A(int w, int h, long cnt){
int[] data = new int[w*h];

//fill with dummy data
for(int x=0; x<w; x++){
for(int y=0; y<h; y++){
//data[x + y*w] = 0xFF000000 + x;

if(cnt>=0){
data[x + y*w] = 0xFFff0000;
cnt--;
}else{
data[x + y*w] = 0xFFa0a0a0;
}

}
}
timeA = System.currentTimeMillis();
Bitmap bm = Bitmap.createBitmap(data, w, h, Bitmap.Config.ARGB_8888);
timeB = System.currentTimeMillis();
return bm;
}

private Bitmap prepareBitmap_B(int w, int h, long cnt){

Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
timeA = System.currentTimeMillis();

//fill with dummy data
for(int x=0; x<w; x++){
for(int y=0; y<h; y++){
//data[x + y*w] = 0xFF000000 + x;

if(cnt>=0){
bm.setPixel(x, y, 0xFFff0000);
cnt--;
}else{
bm.setPixel(x, y, 0xFFa0a0a0);
}

}
}
timeB = System.currentTimeMillis();
return bm;
}

protected void drawSomething(Canvas canvas) {

numberOfPt += 500;
if(numberOfPt > (long)((getWidth()*getHeight()))){
numberOfPt = 0;
}

timeStart = System.currentTimeMillis();
Bitmap bmDummy = prepareBitmap_A(getWidth(), getHeight(), numberOfPt);

canvas.drawColor(Color.BLACK);
timeFillBackground = System.currentTimeMillis();
canvas.drawBitmap(bmDummy,
0, 0, null);
timeDrawBitmap = System.currentTimeMillis();

mainActivity.runOnUiThread(new Runnable() {

@Override
public void run() {
mainActivity.showDur(
timeA - timeStart,
timeB - timeA,
timeFillBackground - timeB,
timeDrawBitmap - timeFillBackground,
timeDrawBitmap - timeStart);
}
});
}

}

Modify activity_main.xml to add TextView to display processing time.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.androidsurfaceview.MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />

<TextView
android:id="@+id/durA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Duration: " />
<TextView
android:id="@+id/durB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Duration: " />
<TextView
android:id="@+id/durFillBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Duration: " />
<TextView
android:id="@+id/durDrawBM"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Duration: " />
<TextView
android:id="@+id/durTotal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Duration: " />

<com.example.androidsurfaceview.MySurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent" />

</LinearLayout>

MainActivity.java
package com.example.androidsurfaceview;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

TextView textDurA, textDurB, textDurFillBack,
textDurDrawBM, textDurTotal;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

textDurA = (TextView)findViewById(R.id.durA);
textDurB = (TextView)findViewById(R.id.durB);
textDurFillBack = (TextView)findViewById(R.id.durFillBack);
textDurDrawBM = (TextView)findViewById(R.id.durDrawBM);
textDurTotal = (TextView)findViewById(R.id.durTotal);

}

protected void showDur(long dA, long dB, long dFill, long dDraw, long dTotal){
textDurA.setText("Duration(ms) - A: " + dA);
textDurB.setText("Duration(ms) - B: " + dB);
textDurFillBack.setText("Duration(ms) - Fill Background: " + dFill);
textDurDrawBM.setText("Duration(ms) - drawBitmap: " + dDraw);
textDurTotal.setText("Duration(ms) - Total: " + dTotal);
}

}

MyThread.java refer to last exercise, "Create animation on SurfaceView in background Thread".


download filesDownload the files.

prepareBitmap_A:

prepareBitmap_B: